2011-01-26 115 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); 
} 
}