2014-04-28 169 views
7

foo方法在下面的例子中给我们一个警告,而bar不是?Java泛型继承警告

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 
    } 

} 
+5

您对类型删除有多少了解?见http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#Type擦除 –

+1

我认为很明显,'foo()'应该给出警告。您正在将对象'y'投射到'Y'的某个未知超类'T'。我也很感兴趣,为什么'bar()'不。我猜编译器能够看到''Y'到'Z'不会导致问题,因为'Z'的定义是可用的。 – SebastianH

+2

@SebastianH:我不认为这是一个问题。 – gudge

回答

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. 
} 
+0

哎呀,忘了扩展位。编辑,谢谢。 – ggovan

0

由于T它的代码类型和Z它的类名。 return (Z) y;其正确的类型转换,但return (T) y; - 在运行时转换为未知类型。有关运行时类型标记的JVM并不知道(请参阅this教程部分)。绝对简短,return (T) y;差不多等效return (Object) y;,它从X.YObject没有检查。有关return (Z) y;的解释,另请参见downcasting in Java

+2

“*'return(T)y;'几乎等价于'return(Object)y;'*”实际上是因为''它在字节码中等价于'return(Y)y;'。 – Pshemo

+2

@Pshemo当然,感谢您的纠正。 – injecto