2011-01-26 74 views
0

我遇到了泛型的下列问题。我想要一个子类BB通过超类B中的方法获得A的子类A的一个实例,它是超类B的字段之一。有人可以告诉我处理这个问题的最佳方法Java泛型问题

请仔细阅读下面的代码(请参阅注释// Problem here),它是自我解释的,我不知道如何用文字表达它。

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); 
} 
} 
+0

这很难理解你的问题。 – 2011-01-26 13:37:16

回答

1

如果你想要的是创建在显着的地方类型参数T的实例,这是不幸的是没有用Java泛型(由于type erasure)成为可能。

如果你想要的是其他东西,请澄清。

+0

在某些情况下,这是可能的。如果具有泛型参数的类是抽象的,我们可以使用反射来检索类型,然后创建一个实例,但这是有风险的。 – 2011-01-26 13:36:13

0

这是一个完整的例子吗?我没有看到在任何地方创建了AAA的任何实例。如果您希望System.out行打印“It works_itchy”,那么您至少需要创建AA的实例。

0

T表示在B类AA的情况下,您将需要在AA的情况下通过,或许在构造函数:

public B(T aaInstance) { 
    this.field = T; 
} 

因为类型擦除,你不能创建在AA的一个实例运行时,如果这就是你想要做的,因为这些类型在编译后不可用。

1

我会用一个factory接口这样的:

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); 
} 
} 
0

这是可能的(但真的很奇怪):

ParameterizedType pt = (ParameterizedType) getClass().getGenericSuperclass(); 
Class<?> cls = (Class<?>) pt.getActualTypeArguments()[0]; 
field = (T) cls.getConstructor(String.class).newInstance(name); 
return field; 
0

另一种选择是离开T getField(String)(和那里B)的抽象和迫使BB提供执行。

0

B需要它创建的类的副本。子类将其传递给构造函数。

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); 
} 
}