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)并且没有分心有问题的代码示例.
在编译时,编译器不知道 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)
弄清楚在什么情况下它与以前的代码不同应该是有启发性的。