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

时间:2017-10-29 20:30:52

标签: 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 { }

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

P.S:我的研究:thisthisThis is also very interesting(“将原语投射到通用”:( T)为真)我的问题更明确地指出问题,问题还在于编译器是否检查了演员(T)并且没有分心有问题的代码示例。

2 个答案:

答案 0 :(得分:2)

这涵盖在JLS Sec 5.5.1

  

给定编译时引用类型S(源)和编译时引用类型T(目标),如果由于以下规则而没有发生编译时错误,则从S到T存在转换转换。

     

...

     

如果T是类类型,则为| S | &lt ;: | T |,或| T | &LT ;: | S |。否则,发生编译时错误。

     

...

     

如果T是一个类型变量,则递归地应用该算法,使用T的上限代替T.

所以编译器使用Object代替T,因此它认为演员合法。

答案 1 :(得分:0)

  

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

我宁愿说编译器不知道 T 会是什么。它可以是例如Object在这种情况下演员表是合法的。在这种情况下,设计师决定允许可能违法的演员不允许合法的演员阵容。

其他问题是编译器无法生成实际的&#34;强制转换为T&#34;因为JVM只有&#34;强制转换为特定的类&#34;指令。所以演员阵容似乎也在运行时成功。

如果您确实想要进行检查演员表,可以通过将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());
}

在你的情况下你可以

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

弄清楚它与以前的代码有什么不同,应该是有益的。

相关问题