为什么"t instanceof T"不允许,其中T是类型参数,t是变量?

whi*_*hat 6 java generics instanceof type-parameter

Eclipse表示,由于泛型橡皮擦,Type Parameter不允许使用instanceof操作.

我同意在运行时,不会保留类型信息.但请考虑以下类的通用声明:

class SomeClass<T>{
    T t;
    SomeClass(Object o){
        System.out.println(o instanceof T);   // Illegal
    }   
}        
Run Code Online (Sandbox Code Playgroud)

在运行时,不会出现T!但是如果我实例化这个类型为Integer的类,那么相应的对象将具有Integer类型的字段t.

那么,为什么我不能用T检查变量的类型,它可以在运行时被Integer替换.而我实际上会做类似"o instanceof Integer"的事情.

在哪些情况下,允许带有类型参数的instanceof会导致故障,从而禁止它?

Pet*_*rey 5

如果在运行时需要T,则需要在运行时提供它.这通常是通过传递T必须的Class <T>来完成的.

class SomeClass<T> {
    final T t;

    public SomeClass(Class<T> tClass, T t) {
        if(!tClass.isAssignableFrom(t.getClass()) throw new IllegalArgumentException("Must be a " + tClass);
        this.t = t;
    }

    private SomeClass(T t) {
        this.t = t;
    }

    public static <T> SomeClass<T> of(Class<T> tClass, T t) {
        if(!tClass.isAssignableFrom(t.getClass()) throw new IllegalArgumentException("Must be a " + tClass);
        return new SomeClass(t);
    }
} 

// doesn't compile
SomeClass<Integer> intSomeClass = SomeClass.of(Integer.class, "one");

Class clazz = Integer.class;
// compiles with a warning and throws an IAE at runtime.
SomeClass<Integer> intSomeClass = (SomeClass<Integer>) SomeClass.of(clazz, "one");

// compiles and runs ok.
SomeClass<Integer> intSomeClass = SomeClass.of(Integer.class, 1);
Run Code Online (Sandbox Code Playgroud)


yan*_*kee 5

但是如果我实例化这个类型为Integer的类,那么相应的对象将具有Integer类型的字段t

不,它不会.它将具有Object类型的字段.每次访问它时,它都会被转换为Integer.

请考虑以下代码:

SomeClass<Integer> c = new SomeClass<Integer>();
SomeClass untyped = (SomeClass)c; // Which type was it?
SomeClass<String> stringTyped = (SomeClass<String>)untyped; // Now it's STRING??
Run Code Online (Sandbox Code Playgroud)

作品.给你一堆编译器警告,但有效.因为字段T实际上是Object类型,可以转换为任何东西.


Nov*_*kov 3

编译后的语句o instanceof T将是o instanceof Objectand 因为所有类型都派生自 Object,所以它将始终评估为 true。允许此类测试会给出假阳性结果