编译器从不检查转换为泛型类型(T)?

Cod*_*ete 5 java generics casting

static <T> void f1(Base arg1, T arg2) {
    T loc = (T) arg1; // why Derived is "kind of cast" to String?
    System.out.println(loc.getClass().getName()); // would print: Derived
}

f1(new Derived(), "sdf");  // T is String - inferred from arg2

class Base { }

class Derived extends Base { }
Run Code Online (Sandbox Code Playgroud)

我的想法是正确的:写作演员(T)意味着"编译器不能也不会检查这个演员".在编译时编译器不知道arg2会是什么(并且它可能是任何东西),因此编译器不能排除强制转换可以工作并且必须信任程序员.因此,在编译时永远不会检查此强制转换.在运行时,局部var声明看起来像Object loc = arg1;(在类型擦除之后).所以一切正常,因为编译器从不关心这个(T)演员?

PS:我的研究:这个,这个.这也很有意思("将原语转换为通用":( T)true)我的问题更明确地指出问题,问题还在于编译器是否检查了演员(T)并且没有分心有问题的代码示例.

Ale*_*nov 1

在编译时,编译器不知道 arg2 是什么(它可以是任何东西),因此编译器不能排除强制转换可以工作的可能性,并且必须信任程序员。

我宁愿说编译器不知道T会发生什么。例如,Object在这种情况下,演员阵容将是合法的。在这种情况下,设计者决定更愿意允许可能非法的演员,而不是不允许可能合法的演员。

另一个问题是编译器无法生成实际的“转换为” T因为 JVM 只有“转换为特定类”指令。因此,转换似乎在运行时也成功了。

如果您确实想要进行检查强制转换,可以通过Class<T>作为额外参数传递来实现:

static <T> void f1(Base arg1, Class<T> clazz) {
    T loc = clazz.cast(arg1); // will throw exception
    System.out.println(loc.getClass().getName());
}
Run Code Online (Sandbox Code Playgroud)

在你的情况下你可以

static <T> void f1(Base arg1, T arg2) {
    T loc = (T) arg2.getClass().cast(arg1);
    System.out.println(loc.getClass().getName());
}
Run Code Online (Sandbox Code Playgroud)

弄清楚在什么情况下它与以前的代码不同应该是有启发性的。