2017-02-09 35 views
-4

我試圖找出以下方法是如何的類型是擦除如何刪除通用列表類型?當我嘗試它自己,它給出了一個錯誤

public class Util { 
    public static <T extends Number> int sum(List<T>list){ 
     int sum=0; 
     for(Number n:list){ 
      sum+=n.intValue(); 
     } 
     return sum; 
    } 
} 

我讀的類型參數與它的第一個綁定的替代。 所以我試過了,卻得到了一個錯誤:編譯器的類型檢查階段後

public static int sum3(List list){ 
    int sum=0; 
    for(Number n:list){   <- Type mismatch: cannot convert from element type Object to Number 
     sum+=n.intValue(); 
    } 
    return sum; 
} 
+0

@Tunaki那個笨蛋真的沒有回答OP的問題。 –

+0

@Andy在for-each循環中使用原始列表不是同一個問題嗎?在鏈接的問題中,他們有'for(String s:perms){''perms'是一個'List',這也是OP在這裏所具有的。 – Tunaki

+0

@Tunaki,但OP是專門詢問「如何刪除以下方法」。該複製品基本上說「不使用原始類型」 - 當然,這是很好的建議 - 但不提供OP顯然想知道的內容。 –

回答

1

你的第二個代碼實際上不是類型擦除後的等效代碼。它不可能,因爲如你所見,增強的for循環將不能編譯。

如果諮詢language spec,它顯示了循環相當於基本爲增強的for循環:

for (I #i = Expression.iterator(); #i.hasNext();) { 
    {VariableModifier} TargetType Identifier = 
     (TargetType) #i.next(); 
    Statement 
} 

這是實際上什麼得到執行:增強的for循環是一個基本的只是語法糖循環看起來像這樣。

因此,編譯器會做你的第一個代碼的第一件事將是「desugar」它:

public static <T extends Number> int sum(List<T>list){ 
    int sum=0; 
    for (Iterator<Number> i = list.iterator(); i.hasNext();) { 
    Number n = (Number) i.next(); 
    sum += n.intValue(); 
    } 
    return sum; 
} 

然後,當是時間申請類型擦除,這將改寫到:

public static int sum(List list){ 
    int sum=0; 
    for (Iterator i = list.iterator(); i.hasNext();) { 
    Number n = (Number) i.next(); 
    sum += n.intValue(); 
    } 
    return sum; 
} 

注意,這裏的唯一不同的是,i.next()是在第一種情況下一個Number,從而使鑄造不必要;但第二個是Object(因爲原始迭代器),所以投射是必要的。

這種形式的擦除代碼編譯。事實上,如果你嘗試反編譯這個版本的代碼,你會發現它的字節碼與OP問題中的第一個代碼相同。

當然,由於Sotirios指出What is a raw type and why shouldn't we use it?這個問題,所以你不應該試圖自己去做類型刪除。但知道它在做什麼是有用的。

+0

這是由於foreach循環而丟失的數字。 – ericj

+0

@ericj它是你失蹤的語法解析,*然後*演員。您無法將演員應用於增強型for循環。 –

+0

是的,我明白了。非常感謝你。 – ericj

0

擦除發生。最終,它會導致你寫的內容,但是類型檢查首先完成。

+0

我寫的不能,因爲它錯誤。 – ericj

+1

@ericj你甚至讀過答案嗎?這裏的關鍵字是*最終*。 – luk2302

相關問題