2013-05-01 84 views
8

任何人都可以解釋爲什麼在y分配線上存在無類型的轉換警告?請注意,x或z分配中沒有警告。意外的未經檢查的轉換警告

public class Entity<T> 
{ 
    @SuppressWarnings("unchecked") 
    public <TX> Entity<TX> typed(Class<TX> type) 
    { 
     return (Entity<TX>) this; 
    } 

    @SuppressWarnings("unchecked") 
    public static <TX> Entity<TX> typed(Entity<?> entity, Class<TX> type) 
    { 
     return (Entity<TX>) entity; 
    } 

    public static void main(final String[] args) 
    { 
     final Entity<?> a = new Entity<Integer>(); 
     final Entity b = (Entity) a; 

     final Entity<Integer> x = a.typed(Integer.class); 
     final Entity<Integer> y = b.typed(Integer.class); 
     final Entity<Integer> z = typed(b, Integer.class); 
    } 
} 
+2

您的實體'b'在從'a'強制轉換後是無類型的,因此當您使用'b.typed(Integer.class)''將其轉換回來時,它是無類型的。泛型類型不同於類類型;他們不被保留,當「失敗」。 – Vulcan 2013-05-01 16:53:31

回答

6

b的類型是Entity,這是一種原始類型。因此,它的API看起來是這樣的:

public Entity typed(Class type) 

所以你將從EntityEntity<Integer>。編譯器已經失去了參數type和返回的實體類型之間的任何關聯,所以它不能進行任何檢查。

換一種方式,你可以使用:

final Entity<Integer> y = b.typed(String.class); 

...並且仍然只接收相同的警告。如果您嘗試使用xz進行相同的更改,您將會收到編譯時錯誤。

編輯:正如註釋中指出的那樣,您使用原始類型的事實將刪除泛型的所有痕跡。

JLS section 4.8

爲了促進與非通用舊代碼交互,能夠爲一種類型使用擦除(§4.6)的參數化類型(§4.5)或的擦除的數組類型(第10.1節),其元素類型是參數化類型。這種類型被稱爲原始類型。構造或方法不具有參數化的類型或類型變量簽名

類型擦除也映射簽名(§8.4.2):

然後在section 4.6。構造函數或方法簽名的刪除是一個由與s相同名稱和s中所有形式參數類型的刪除組成的簽名。

+1

請注意,「類型」方法本身是參數化的。有兩個類型參數。 – 2013-05-01 16:54:11

+4

@KonstantinKomissarchik:沒關係 - 當你調用一個原始類型的方法時,一切都會消失。 – 2013-05-01 16:55:12

+0

除編譯器不是說我正在調用原始類型的方法。這是說,我正在從Entity到Entity 的轉讓中進行未經檢查的轉換。該類型如果完全由TX指定。 – 2013-05-01 16:57:58

0

你是「downcasting」a,在分配給b時刪除它的類型標識符。由於b現在是無類型的,因此您將獲得無類型的轉換警告,因爲它不再知道類型。

1

從聲明:

final Entity<?> a = new Entity<Integer>(); 

a被輸入,因此該方法調用a.typed(Integer.class)也打出來。

typed(b, Integer.class)它的工作原理是因爲該方法是通用的。

final Entity b = (Entity) a; 

你已經截止仿製藥(用於b通過使用原始型的,而不是Entity通用版本),所以調用b.typed(Integer.class)是類型化的。所以你得到警告。

相關問題