我們可以製作class Foo <T>
,爲什麼我不能撥打new T()
? 我試着瞭解,我知道T
是一個類型變量,但沒有得到答案......這是朋友問的,也渴望知道答案......請提前致謝。我們可以讓Foo <T>,爲什麼我不能叫新的T()?
2
A
回答
2
因爲你不知道T是否可以實例化,它可能有一個私有構造函數。
試想:
class Foo<T> {
public Foo() {
new T();
}
}
class Bar {
private Bar() {}
}
class FooBar {
public FooBar() {
Foo<Bar> foo = new Foo<>();
}
}
7
這是因爲type erasure。 T的類只在編譯時才知道,而不是在運行時。
有一種解決方法。您可以添加Class<T>
類型的其他方法參數,然後在該參數上調用newInstance
。確保你閱讀文檔進行反思,並在嘗試之前知道你正在進入的內容。
+0
有一個特殊情況'class Bar擴展Foo
0
的問題是類型擦除的注意,但Taymon。你可以使用反射和子類來解決它,所以類型信息在運行時保持不變。
請注意,它適用於Bar,但不適用於Qux。請注意,Bar通過使用固定類型參數Baz擴展Foo來指定編譯它的類型參數。實例化也依賴於一個可訪問的零參數構造函數。
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import sun.reflect.generics.reflectiveObjects.TypeVariableImpl;
// Made abstract so we can use getClass().getGenericSuperclass() and rely on subclasses
// specifying it's type parameter.
public abstract class Foo<T> {
public T instantiateTypeParameter() throws Exception {
Type type = getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
ParameterizedType paramType = (ParameterizedType) type;
Type typeArg = paramType.getActualTypeArguments()[0]; // We know it's only one, T
if (typeArg instanceof TypeVariableImpl) {
// Type is not specified. Can't do anything to retrieve it at runtime
TypeVariableImpl typeVar = (TypeVariableImpl) typeArg;
for (TypeVariable var : typeVar.getGenericDeclaration().getTypeParameters()) {
System.out.println("Type: " + var);
}
return null;
} else {
Class<?> clazz = (Class<?>) typeArg;
return (T) clazz.getConstructor().newInstance();
}
} else {
System.out.println("IMPOSSIBRUUU");
return null;
}
}
}
public class Bar extends Foo<Baz> {
}
public class Qux<T> extends Foo<T> {
}
public static void main(String[] args) throws Exception {
Bar bar = new Bar();
Baz baz = bar.instantiateTypeParameter(); // Note that you know that it returns Baz
System.out.println("Baz: " + baz); // It works!
Qux<Baz> qux = new Qux<Baz>();
Baz baz2 = qux.instantiateTypeParameter(); // Will be null
System.out.println("Baz2: " + baz2);
}
相關問題
- 1. 爲什麼我不能有std ::可選<T>其中T是抽象的?
- 2. 爲什麼我不能將IEnumerable <T>列表投射到BindingList <t>?
- 3. 你叫什麼IEnumerable <Foo>?
- 4. profiler:我可以找到什麼叫我的功能?
- 5. Java:什麼是 - public static <T> foo(){...}?
- 6. 我們爲什麼可以在VB
- 7. 爲什麼我們需要IEqualityComparer,IEqualityComparer <T>接口?
- 8. 爲什麼不能讓我分析JSON?
- 9. 爲什麼我們不能重寫`||`和`&&`?
- 10. 爲什麼我們不能循環'...'?
- 11. Scala:爲什麼我們不能做super.val?
- 12. 爲什麼要讓shared_ptr <T[N]>?
- 13. 我可以知道什麼叫applicationShouldHandleReopen?
- 14. 爲什麼「foo = foo || {};」不行?
- 15. 我爲什麼要使用TCollections.CreateList <T>而不是TList <T>。創建
- 16. 爲什麼我可以讓我的mysqli_fetch_assoc工作?
- 17. 爲什麼我們不能從Object []轉換爲String [],而我們可以從數組中的值?
- 18. 爲什麼不是我的清單<t>排序工作?
- 19. 我不能用keytool做什麼,我可以用OpenSSL做什麼?
- 20. 爲什麼我不能說打印$ somehash {$ var} {fh}「foo」?
- 21. 爲什麼你可以在聲明sub foo之前調用foo()和&foo,但是你不能調用plain foo?
- 22. 爲什麼vim -t ctags不夠?我不能跳轉到我想要的功能
- 23. 爲什麼我可以重新綁定,但是我不能在git中合併?
- 24. 爲什麼ReadOnlyCollection <T>不是ReadOnlyList <T>?
- 25. 我們可以使用Q_PROPERTY和模板<typename T>嗎?
- 26. 爲什麼我們不能宣佈矢量<INT,對< int, int >>
- 27. 爲什麼我不能讓我的jQuery leftScroll動畫起作用?
- 28. 爲什麼我不能讓我的Pygame Sprite在OSX上移動?
- 29. 爲什麼Javascript不讓我關閉我的功能?
- 30. 爲什麼我不能讓我的風格下降?
參見[什麼是具體化泛型,他們是如何解決類型擦除問題,爲什麼他們不能沒有大的變化被添加?](http://stackoverflow.com/questions/879855) – McDowell 2012-08-01 12:37:15