我们可以做class Foo <T>
,为什么我不能打电话new T()
?我试图理解,我知道这T
是一个类型变量,但没有得到那个答案......这是朋友问的,我也很想知道答案......请提前谢谢。
问问题
516 次
3 回答
7
这是因为类型擦除。T 的类仅在编译时已知,而不是在运行时。
有一种解决方法。您可以添加一个额外的方法类型参数,Class<T>
然后调用newInstance
该参数。确保您阅读文档以进行反思,否则在尝试此操作之前知道您要进入的内容。
于 2012-08-01T12:37:18.627 回答
2
因为您甚至无法知道 T 是否可实例化,所以它可能有一个私有构造函数。
想象:
class Foo<T> {
public Foo() {
new T();
}
}
class Bar {
private Bar() {}
}
class FooBar {
public FooBar() {
Foo<Bar> foo = new Foo<>();
}
}
于 2012-08-01T12:37:26.317 回答
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);
}
于 2012-08-01T13:46:39.523 回答