2010-11-19 73 views
5

我期望這個代碼拋出ClassCastException:爲什麼這種通用演員不會失敗?

public class Generics { 
    public static void main(String[] args) { 
     method(Integer.class); 
    } 

    public static <T> T method(Class<T> t) { 
     return (T) new String(); 
    } 
} 

但事實並非如此。鑄造字符串T沒有失敗,直到我用返回的對象以某種方式,如:

public class Generics { 
    public static void main(String[] args) { 
     method(Integer.class).intValue(); 
    } 

    public static <T> T method(Class<T> t) { 
     return (T) new String(); 
    } 
} 

背景:我創建了使用JAXB解組一個XML文件中的類。它看起來像這樣:

public static <T> T unmarshal(File file, Class<? extends T> clazz) 

根據根元素是否是一個匿名類型或不是,正在返回T或JAXBElement的。 JAXBElement當然不能被鑄造成T. 在我的單元測試中,我只調用了unmarshal()而沒有對結果做任何事情,一切正常。在代碼中,它失敗了。

爲什麼它不直接失敗?這是一個錯誤?如果沒有,我想明白爲什麼。

+1

那麼,它*會產生警告。 – Jeremy 2010-11-19 12:54:09

回答

4

您沒有明確指定,所以T是Object。

所以查找這個樣子的

public class Generics { 

    public static void main(String[] args) { 
     Generics.method(Integer.class).intValue(); 
    } 

    public static Object method(Class<Object> t) { 
     return (Object) new String(); 
    } 
} 

如果指定了泛型參數:

public class Generics { 

    public static void main(String[] args) { 
     Generics.<Integer>method(Integer.class).intValue(); 
    } 

    public static <T> T method(Class<T> t) { 
     return (T) new String(); 
    } 
} 

你會得到異常。

4

如果未明確指定T,則類型擦除將其視爲Object。因此,您的String對象可以被鑄造...

1

我認爲你可以做更強大的方法定義是這樣的:

public static <T extends Number> T method(Class<T> t) { 
    return //// some code. 
} 

在這種情況下,行返回新的String()就不能進行編譯。

但行返回新的整數(123);被編譯,工作並不需要投射。