I'm trying to generalize a method that I'll need to call a lot. It takes a List<E extends RealmObject> and return a List<T extends Pojo<E>>. The conversion from E to T is done via
new T().fromRealm(realmObject)
It won't work because T is an abstract class, so I can't instantiate it.
public static <E extends RealmObject, T extends Pojo<E>> List<T> fromRealmList(
RealmList<E> realmList) {
List<T> pojoObjects = new ArrayList<>();
if (realmList != null) {
for (E realmObject : realmList) {
try {
pojoObjects.add(new T().fromRealm(realmObject));
} catch (Exception e) {
e.printStackTrace();
}
}
}
return pojoObjects;
}
I also tried with this answer, but List<T> won't accept the object created with clazz.newInstance().
EDIT: adding Pojo class
public abstract class Pojo<R extends RealmObject> {
#NonNull
public abstract R toRealm();
#NonNull
public abstract Pojo<R> fromRealm(R realmObject);
}
EDIT2: adding an alternate solution, that still doesn't work: Required T, found Pojo<E>.
T newInstance = clazz.getConstructor()
.newInstance()
.fromRealm(realmObject);
pojoObjects.add(newInstance);
Apart from being an abstract class, T is also a parameter type, which cannot be used in a constructor new T().
A typical solution would be to use reflection:
pass an additional parameter Class<T> clazz to your method fromRealmList
invoke clazz.getConstructor(...).newInstance(...)
Maybe not perfect but that should work.
--edit-- The below is an example without using type T:
public static <E extends RealmObject> List<Pojo<E>> fromRealmList(
RealmList<E> realmList, Class<Pojo<E>> clazz) {
List<Pojo<E>> pojoObjects = new ArrayList<>();
...
Pojo<E> newInstance = clazz.getConstructor(...).newInstance(...).fromRealm(...);
pojoObjects.add(newInstance);
...
}
Related
I have got a template class as follows:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
How do I create a new instance of T in my class?
After type erasure, all that is known about T is that it is some subclass of Object. You need to specify some factory to create instances of T.
One approach could use a Supplier<T>:
class MyClass<T> {
private final Supplier<? extends T> ctor;
private T field;
MyClass(Supplier<? extends T> ctor) {
this.ctor = Objects.requireNonNull(ctor);
}
public void myMethod() {
field = ctor.get();
}
}
Usage might look like this:
MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);
Alternatively, you can provide a Class<T> object, and then use reflection.
class MyClass<T> {
private final Constructor<? extends T> ctor;
private T field;
MyClass(Class<? extends T> impl) throws NoSuchMethodException {
this.ctor = impl.getConstructor();
}
public void myMethod() throws Exception {
field = ctor.newInstance();
}
}
Another non-reflective approach is to use a hybrid Builder / Abstract Factory pattern.
In Effective Java, Joshua Bloch goes over the Builder pattern in detail, and advocates a generic Builder interface:
public interface Builder<T> {
public T build();
}
Concrete builders can implement this interface, and outside classes can use the concrete builder to configure the Builder as required. The builder can be passed to MyClass as a Builder<T>.
Using this pattern, you can get new instances of T, even if T has constructor parameters or requires additional configuration. Of course, you'll need some way to pass the Builder into MyClass. If you can't pass anything into MyClass, then Builder and Abstract Factory are out.
This may be more heavyweight than what you're looking for, but it will also work. Note that if you take this approach, it would make more sense to inject the factory into MyClass when it is constructed instead of passing it into your method each time it is called.
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}
If you're willing to subclass you can avoid erasure as well, check out
http://www.artima.com/weblogs/viewpost.jsp?thread=208860
You can get the class object of type T without passing any arguments.
Try this.
static class MyClass<T> {
Class<?> clazz;
#SafeVarargs
public MyClass(T... dummy) {
if (dummy.length > 0)
throw new IllegalArgumentException("Do not specify arguments");
clazz = dummy.getClass().componentType();
}
#Override
public String toString() {
return "MyClass<T = " + clazz.getName() + ">";
}
}
public static void main(String[] args) {
MyClass<String> s = new MyClass<>();
System.out.println(s);
Object i = new MyClass<Integer>();
System.out.println(i);
}
output:
MyClass<T = java.lang.String>
MyClass<T = java.lang.Integer>
You can instantiate an object of type parameter T like this.
clazz.getConstructor().newInstance();
One option would be to cast it with Object
{field = (T) new Object();}
field will initially be type Object, but then it will cast down to type T. This is an ugly one because reducing casting to zero is what the goal should be for object initializations. But I think this will work.
Class classOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}
Consider the following Java method:
<T extends List<T>> List<T> getMyList() {
return Collections.emptyList();
}
I can assign its output to a variable with a raw type, like so:
List x = getMyList();
List<List> y = getMyList();
But, I can't think of any way to assign its output to a fully parameterized type. In particular, I can't think of a non-raw, concrete type T that would satisfy List<T> z = getMyList();
Can we create such a T ?
If not, why not?
For context, I created this question while trying to understand how Enums are implemented in Java.
Here's an example of a concrete type that both works and starts to hint at a possible use-case (registration of some sort). The type consists acts like both an instance of some type, and as a container for all instances of that type.
public class WeirdEnum extends AbstractList<WeirdEnum> {
private static List<WeirdEnum> underlyingList = new ArrayList<>();
#Override
public WeirdEnum get(int index) { return underlyingList.get(index); }
#Override
public int size() { return underlyingList.size(); }
static <T extends List<T>> List<T> getAList() {
return Collections.emptyList();
}
public WeirdEnum() {
underlyingList.add(this); // Sufficient for our example but not a good idea due to concurrency concerns.
}
static List<WeirdEnum> foo = WeirdEnum.getAList();
}
Not sure if I fully understand your question, but here's an example:
class Example<T> implements List<Example<T>> {
...
}
...
List<Example<String>> list = getMyList();
Every enum in Java extends from the base-enum-class Enum<T extends Enum<T>>, where T is the actual type of the implementing enum.
When writing SomeClass<T extends SomeClass<T>> you can enforce that the type-parameter is always the implementing class itself.
Let's say you have this interface:
public interface MyInterface<T extends MyInterface<T>> {
T getSelf();
}
And this implementing class:
public class MyClass implements MyInterface<MyClass> {
public MyClass getSelf() {
return this;
}
}
In MyClass it is not possible to use any other type-parameter than MyClass itself.
I have got a template class as follows:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
How do I create a new instance of T in my class?
After type erasure, all that is known about T is that it is some subclass of Object. You need to specify some factory to create instances of T.
One approach could use a Supplier<T>:
class MyClass<T> {
private final Supplier<? extends T> ctor;
private T field;
MyClass(Supplier<? extends T> ctor) {
this.ctor = Objects.requireNonNull(ctor);
}
public void myMethod() {
field = ctor.get();
}
}
Usage might look like this:
MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);
Alternatively, you can provide a Class<T> object, and then use reflection.
class MyClass<T> {
private final Constructor<? extends T> ctor;
private T field;
MyClass(Class<? extends T> impl) throws NoSuchMethodException {
this.ctor = impl.getConstructor();
}
public void myMethod() throws Exception {
field = ctor.newInstance();
}
}
Another non-reflective approach is to use a hybrid Builder / Abstract Factory pattern.
In Effective Java, Joshua Bloch goes over the Builder pattern in detail, and advocates a generic Builder interface:
public interface Builder<T> {
public T build();
}
Concrete builders can implement this interface, and outside classes can use the concrete builder to configure the Builder as required. The builder can be passed to MyClass as a Builder<T>.
Using this pattern, you can get new instances of T, even if T has constructor parameters or requires additional configuration. Of course, you'll need some way to pass the Builder into MyClass. If you can't pass anything into MyClass, then Builder and Abstract Factory are out.
This may be more heavyweight than what you're looking for, but it will also work. Note that if you take this approach, it would make more sense to inject the factory into MyClass when it is constructed instead of passing it into your method each time it is called.
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}
If you're willing to subclass you can avoid erasure as well, check out
http://www.artima.com/weblogs/viewpost.jsp?thread=208860
You can get the class object of type T without passing any arguments.
Try this.
static class MyClass<T> {
Class<?> clazz;
#SafeVarargs
public MyClass(T... dummy) {
if (dummy.length > 0)
throw new IllegalArgumentException("Do not specify arguments");
clazz = dummy.getClass().componentType();
}
#Override
public String toString() {
return "MyClass<T = " + clazz.getName() + ">";
}
}
public static void main(String[] args) {
MyClass<String> s = new MyClass<>();
System.out.println(s);
Object i = new MyClass<Integer>();
System.out.println(i);
}
output:
MyClass<T = java.lang.String>
MyClass<T = java.lang.Integer>
You can instantiate an object of type parameter T like this.
clazz.getConstructor().newInstance();
One option would be to cast it with Object
{field = (T) new Object();}
field will initially be type Object, but then it will cast down to type T. This is an ugly one because reducing casting to zero is what the goal should be for object initializations. But I think this will work.
Class classOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}
Imagine we have following classes:
public interface MyInterface<T> {
List<T> getList(T t);
}
abstract class BaseClass<T extends Number> implements MyInterface<T> {
#Override
public List<T> getList(Number t) {
return null;
}
}
class ChildClass extends BaseClass<Integer> {
#Override
public List<Integer> getList(Integer t) {
return super.getList(t); //this doesn't compile
}
}
getList in ChildClass doesn't compile, the output is:
abstract method getList(T) in com.mypackage.MyInterface cannot be accessed directly
I can't get why BaseClass.getList method isn't overriden in ChildClass.
But what makes me completely confused is the fix that makes it compile:
class ChildClass extends BaseClass<Integer> {
#Override
public List<Integer> getList(Integer t) {
return super.getList((Number) t); //Now it compiles!
}
}
So I cast Integer to Number, and is solves the problem.
Could anyone explain what's going on in this code?
Your base class should look like:
abstract class BaseClass<T extends Number> implements MyInterface<T> {
#Override
public List<T> getList(T t) {
return null;
}
}
You weren't using T, but the Number class as a parameter.
It doesn't override because the abstract method takes a Number as a parameter and the concrete method takes an Integer. They must be the same in order to override.
You should change your abstract class implementation to take type T as a parameter.
Why isn't the superclass method defined as
public List<T> getList(T t)
?
What is going on in the imaginary class.
abstract class BaseClass<T extends Number> implements MyInterface<T> {
#Override
public List<T> getList(Number t) {
return null;
}
}
This class has one generic parameter (T) that has to extend Number class and implement the interface MyInterface
You also Try to override a method that does not exists, because this class do not extend other any class. While a class is implementing an interface there is no need to override the interface method because the are only the description.
What happen if we remove the #override annotation.
abstract class BaseClass<T extends Number> implements MyInterface<T> {
public List<T> getList(Number t) {
return null;
}
}
In this case we do not implement the method from the interface but create a new one, a this method parameter is Number that is same type as T, it will probably cause some error that class has two the same methods. (not tested by compiler)
Them implementation of this method should look like this
abstract class BaseClass<T extends Number> implements MyInterface<T> {
public List<T> getList(T t) { //Because T is allready restricted to be Number
return null;
}
}
And when You specify the type You will not have a problem to call this method when you override it
class ChildClass extends BaseClass<Integer> {
#Override
public List<Integer> getList(Integer t) {
return super.getList(t);
}
}
In advance You don have to implement it only for return null and then override it in some child class. What You can do is create class like this
abstract class BaseClass<T extends Number> implements MyInterface<T> {
private List<T> list = new ArrayList<T>(); //The way of initialization is up to You
public List<T> getList() { //Because T is allready restricted to be Number
return list;
}
}
As other colleagues pointed out the reason for issue is incorrect signature of parent method. The reason why the casting works is due to the way how compiler treats generics. It guarantees that there won't be runtime ClassCastException issues if you use generic but only if you don't do casting. As soon as you did it you actually said compiler to shut up as you know better what your type really is. However after this you potentially could get ClassCastException in runtime (not in this case I assume)
I have got a template class as follows:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
How do I create a new instance of T in my class?
After type erasure, all that is known about T is that it is some subclass of Object. You need to specify some factory to create instances of T.
One approach could use a Supplier<T>:
class MyClass<T> {
private final Supplier<? extends T> ctor;
private T field;
MyClass(Supplier<? extends T> ctor) {
this.ctor = Objects.requireNonNull(ctor);
}
public void myMethod() {
field = ctor.get();
}
}
Usage might look like this:
MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);
Alternatively, you can provide a Class<T> object, and then use reflection.
class MyClass<T> {
private final Constructor<? extends T> ctor;
private T field;
MyClass(Class<? extends T> impl) throws NoSuchMethodException {
this.ctor = impl.getConstructor();
}
public void myMethod() throws Exception {
field = ctor.newInstance();
}
}
Another non-reflective approach is to use a hybrid Builder / Abstract Factory pattern.
In Effective Java, Joshua Bloch goes over the Builder pattern in detail, and advocates a generic Builder interface:
public interface Builder<T> {
public T build();
}
Concrete builders can implement this interface, and outside classes can use the concrete builder to configure the Builder as required. The builder can be passed to MyClass as a Builder<T>.
Using this pattern, you can get new instances of T, even if T has constructor parameters or requires additional configuration. Of course, you'll need some way to pass the Builder into MyClass. If you can't pass anything into MyClass, then Builder and Abstract Factory are out.
This may be more heavyweight than what you're looking for, but it will also work. Note that if you take this approach, it would make more sense to inject the factory into MyClass when it is constructed instead of passing it into your method each time it is called.
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}
If you're willing to subclass you can avoid erasure as well, check out
http://www.artima.com/weblogs/viewpost.jsp?thread=208860
You can get the class object of type T without passing any arguments.
Try this.
static class MyClass<T> {
Class<?> clazz;
#SafeVarargs
public MyClass(T... dummy) {
if (dummy.length > 0)
throw new IllegalArgumentException("Do not specify arguments");
clazz = dummy.getClass().componentType();
}
#Override
public String toString() {
return "MyClass<T = " + clazz.getName() + ">";
}
}
public static void main(String[] args) {
MyClass<String> s = new MyClass<>();
System.out.println(s);
Object i = new MyClass<Integer>();
System.out.println(i);
}
output:
MyClass<T = java.lang.String>
MyClass<T = java.lang.Integer>
You can instantiate an object of type parameter T like this.
clazz.getConstructor().newInstance();
One option would be to cast it with Object
{field = (T) new Object();}
field will initially be type Object, but then it will cast down to type T. This is an ugly one because reducing casting to zero is what the goal should be for object initializations. But I think this will work.
Class classOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}