I am creating a function with a generic type and that generic type is an abstract type which I need to instantiate. This code will explain it more clearly:
public <T extends AbstractRow> foo(){//no I did not actually name the function foo
ArrayList<T> arr=new ArrayList<T>();
arr.add(new T(...)); //cant instantiate objects of abstract class
}
Basically I want to enforce "T extends AbstractRow but is not Abstract itself".
I realize you can't instantiate abstract classes, so I'd like a suggestion on a workaround or some other method that would allow me to mimic the behavior of creating an object of a generic type.
As far as I know, there's two ways to do this:
Class<T> type
field to your abstract generic class, and set it through the constructor (or another method). You can then invoke type.newInstance()
to create the object.Factory<T>
with a T create()
method and set that as a field on your abstract class through the constructor (or another method). Upon creating a concrete instance of your generic class, you also have to pass a concrete implementation of said factory.import java.util.ArrayList;
import java.util.List;
public class Generic<T> {
private Factory<T> factory;
public Generic(Factory<T> factory) {
this.factory = factory;
}
public void foo() {
List<T> list = new ArrayList<>();
list.add(factory.create());
}
}
interface Factory<T> {
T create();
}
Usage:
Generic<Bar> concrete = new Generic<>(new Factory<Bar>() {
@Override
public Bar create() {
return new Bar();
}
});
concrete.foo();
Your main issue isn't that you're working with an abstract class - in which case the suggestions posted in the comments would be useful. The bigger problem is that you're trying to instantiate a generic type directly (read: new T()
) - which, simply put, you can't do in Java because of type erasure.
That said, there's always a workaround:
/**@param clazz the subclass you want to instantiate */
public <T extends AbstractRow> foo(Class<T> clazz) {
ArrayList<T> arr = new ArrayList<T>();
arr.add(clazz.newInstance); //instantiate new instance of given subclass
}
Usage:
abstract class Test1 {}
class Test2 extends Test1{ }
class Test<T> {
public static <T extends Test1> T foo(Class<T> clazz) {
T toReturn = null;
try{ toReturn = clazz.newInstance(); } catch (Exception e) { };
return toReturn ;
}
public static void main(String[] args) {
Test1 t1 = t.foo(test2.class);
System.out.println(t1.getClass()); //prints "class pkgname.test2"
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With