繁体   English   中英

我们可以上课Foo <T> ,为什么我不能调用新的T()?

[英]We can make class Foo <T>, why can't I call new T()?

我们可以制作class Foo <T> ,为什么我不能调用new T() 我试着理解,我知道T是一个类型变量,但没有得到答案......这是朋友问的,我也很想知道答案......拜托,提前谢谢。

这是因为类型擦除 T类只在编译时才知道,而不是在运行时。

有一个解决方法。 您可以添加类型为Class<T>的其他方法参数,然后在该参数上调用newInstance 确保您在阅读文档时进行了反思,并在尝试之前了解了您的内容。

因为您无法知道T是否可以实例化,所以它可能有一个私有构造函数。

想像:

class Foo<T> {

    public Foo() {
        new T();
    }
}

class Bar {
    private Bar() {}
}

class FooBar {
    public FooBar() {
       Foo<Bar> foo = new Foo<>();
    }
}

问题是Type Erasure,但是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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM