Reputation: 1
I am stuck with the following problem with generics. i want a subclass BB to get a instance of a subclass of A, which is one of the fields of its super class B, through the method in the super class B. could someone please tell me the best way to handle this problem
please go through the code below (See the comment //Problem here), it is self explanatory and i don't know how to put it in words anyways.
public class A {
String name;
A(String name){
this.name = name;
}
}
public class AA extends A{
String itchy
AA(String name) {
super(name);
this.itchy = name+"_itchy";
}
}
public class B<T extends A> {
T field;
T getField(String name) throws InstantiationException, IllegalAccessException{
//Problem here
field = // instance of AA; how do i do this?
return field;
}
}
public class BB extends B<AA>{
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
BB b = new BB();
System.out.println(b.getField("It works").name);
}
}
Upvotes: 0
Views: 184
Reputation: 1260
B needs a copy of what class it creates. The subclasses pass this into the constructor.
public class B<T extends A> {
final Class<T> classT;
B(Class<T> classT) { classT=classT; )
T field;
T getField(String name) throws InstantiationException, IllegalAccessException{
//Problem here
field = classT.newInstance();
return field;
}
}
public class BB extends B<AA>{
BB() { super(AA.class); }
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
BB b = new BB();
System.out.println(b.getField("It works").name);
}
}
Upvotes: 0
Reputation: 11037
Another option is to leave T getField(String)
(and there for B) abstract and force BB to provide the implementation.
Upvotes: 0
Reputation: 12817
It is possible (but really strange):
ParameterizedType pt = (ParameterizedType) getClass().getGenericSuperclass();
Class<?> cls = (Class<?>) pt.getActualTypeArguments()[0];
field = (T) cls.getConstructor(String.class).newInstance(name);
return field;
Upvotes: 0
Reputation: 48659
I would use a factory interface for this:
public interface Factory<T extends AA> {
T create(String name);
}
public class AAFactory implements Factory<AA> {
AA create(String name) {
return new AA(name);
}
}
public class B<T extends A> {
B(Factory<T> factory) {
this.factory = factory;
}
Factory<T> factory;
T field;
T getField(String name) {
field = factory.create(name);
return field;
}
}
public class BB extends B<AA>{
BB() {
super(new AAFactory());
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
BB b = new BB();
System.out.println(b.getField("It works").name);
}
}
Upvotes: 1
Reputation: 7696
T represents an instance of AA in class B. You would need to pass in an instance of AA, maybe in a constructor:
public B(T aaInstance) {
this.field = T;
}
Because of type erasure, you cannot create an instance of AA at runtime, if that is what you are looking to do, because the types are not available after compilation.
Upvotes: 0
Reputation: 24291
Is it a complete example? I don't see any instance of A
or AA
being created anywhere. If you expect the System.out
line to print "It works_itchy", then you need to create at least instance of AA
.
Upvotes: 0
Reputation: 116306
If what you want is to create an instance of the type parameter T
at the marked place, it is unfortunately not possible with Java generics (due to type erasure).
If what you want is something else, please clarify.
Upvotes: 1