以下示例中的foo
方法向我们发出警告,而bar
则没有?
public class X {
static class Y {}
static class Z extends Y {}
Y y = new Y();
<T extends Y> T foo() {
return (T) y; // warning - Unchecked cast from X.Y to T
}
Z bar() {
return (Z) y; // compiles fine
}
}
答案 0 :(得分:1)
类型T在编译时被删除到Y,这是泛型如何在Java中工作。因此,当在运行时执行强制转换时,T的类型不可用,它只是字节代码中的Y
。
bar()
编译好,因为所有类型信息都可用(演员表将失败)。但foo()
缺少此类型信息,并且不会失败,可能(或者当然,在这种情况下)使方法的类型签名不正确并成为程序中的错误源。
要安全地执行此操作,您需要将类本身传递给方法。
<T extends Y> T foo(Class<T> cls) {
return cls.cast(y); //No type warning. Will throw an error when cast fails.
}
答案 1 :(得分:0)
因为T
是一个类型标记而Z
是一个类名。 return (Z) y;
它的正确类型转换,但是return (T) y;
- 在运行时转换为未知类型。 JVM在运行时对类型标记一无所知(参见this教程部分)。绝对简短,return (T) y;
几乎等效return (Object) y;
,从X.Y
到Object
取消选中。另请参阅有关return (Z) y;
解释的downcasting in Java。