2010-04-22 71 views
24

我想我會得到什麼未經檢查的投射手段(從一個投射到另一個不同類型),但是「檢查」投射是什麼意思?如何檢查演員陣容,以便在Eclipse中避免此警告?什麼是未經檢查的演員,我如何檢查它?

+1

發表我的源代碼。 – 2010-04-22 17:54:31

+12

不要發佈代碼!不要讓他們給你一條魚,而不是教導釣魚:)不,嚴肅地說,即使問題是以業餘風格被問到,是否應該對通用問題有一個通用的答案。 – Mike 2014-07-15 15:25:32

回答

28

未經檢查的轉換意味着您(隱式或顯式)從泛型類型轉換爲非限定類型或以其他方式轉換。例如。這條線

Set<String> set = new HashSet(); 

會產生這樣的警告。

通常這樣的警告有很好的理由,所以你應該嘗試改進你的代碼而不是壓制警告。來自Effective Java的報價,第二版:

消除每一個未經檢查的警告,你可以。如果你消除了所有的警告,你可以放心,你的代碼是類型安全的,這是一件很好的事情。這意味着您在運行時不會得到ClassCastException,並且它會增加您對程序運行的信心。

如果不能消除警告,可以證明該 引發警告的代碼是類型安全的,那麼(只有這樣)與@SuppressWarnings("unchecked")註解抑制警告 。如果您在沒有首先證明代碼是類型安全的情況下取消警告 ,那麼您只會給自己一個虛假的安全感。代碼可以在不發出任何警告的情況下進行編譯,但在運行時它仍然可以拋出ClassCastException。但是,如果您忽略 未經檢查的警告(您知道這些警告是安全的(而不是禁止它們)),那麼您的 將不會注意到何時出現一個代表真正問題的新警告。新的警告將在你沒有沉默的所有虛假警報中消失。

當然,消除警告並不總是像上面的代碼那樣容易。沒有看到你的代碼,沒有辦法告訴如何使它安全。

+0

這樣如何未選中鑄造: 'FoodBag BAG2 =新FoodBag ();'' ((FoodBag )BAG2).setFood(新CheeseSandwich());' 從一個普通類型的泛型類型? – Datoraki 2011-04-21 14:57:39

+0

@Datoraki,你能對你的問題更具體嗎? – 2011-04-21 15:10:27

+19

-1因爲答案沒有解決「如何檢查投射」問題的一部分。好的,我們知道我們應該檢查演員,**我們該怎麼做? – Mike 2014-07-14 14:44:24

39

要ellaborate詳細瞭解有關彼得寫道:

從非泛型類型泛型類型強制轉換可能工作在運行時間就好了,因爲通用參數在編譯過程中刪除,因此,我們只剩下一個合法的演員。但是,由於有關類型參數的錯誤假設,代碼可能會在以後出現意外的ClassCastException時失敗。例如:

List l1 = new ArrayList(); 
l1.add(33); 
ArrayList<String> l2 = (ArrayList<String>) l1; 
String s = l2.get(0); 

未檢查的警告在第3行表示該編譯器不能保證類型安全了,在這個意義上,一個意想不到的ClassCastException異常可能somewere後occure。這發生在第4行,它執行隱式轉換。

+5

這應該是被接受的答案 – CodyBugstein 2013-08-12 18:41:37

0

與檢查強制轉換相反,未經檢查的強制轉換不會在運行時檢查類型安全性。

下面是一個基於3rd ed的Consider typesafe heterogenous containers部分的示例。「有效的Java」由Joshua布洛赫,但容器類的故意損壞 - 它保存並返回錯誤類型:

public class Test { 

    private static class BrokenGenericContainer{ 
     private final Map<Class<?>, Object> map= new HashMap<>(); 

     public <T> void store(Class<T> key, T value){ 
      map.put(key, "broken!"); // should've been [value] here instead of "broken!" 
     } 

     public <T> T retrieve(Class<T> key){ 
//   return key.cast(map.get(key)); // a checked cast 
      return (T)map.get(key);  // an unchecked cast 
     } 

    } 

    public static void main(String[] args) { 
     BrokenGenericContainer c= new BrokenGenericContainer(); 
     c.store(Integer.class, 42); 
     List<Integer> ints = new ArrayList<>(); 
     ints.add(c.retrieve(Integer.class)); 
     Integer i = ints.get(0); 
    } 

} 


如果retrieve()使用的選中投 - (T)map.get(key) - 運行此程序會導致ClassCastException發生在Integer i = ints.get(0)一行。該retrieve()方法完成,因爲實際的類型沒有在運行時檢查:

Exception in thread "main" 
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
    at Test.main(Test.java:27) 


但如果retrieve()使用檢查轉換 - key.cast(map.get(key)) - 運行此程序會導致ClassCastExceptionkey.cast(map.get(key))線中發生,因爲檢查過的演員會發現該類型錯誤並拋出異常。該retrieve()方法將無法完成:

Exception in thread "main" java.lang.ClassCastException: 
              Cannot cast java.lang.String to java.lang.Integer 
    at java.lang.Class.cast(Class.java:3369) 
    at Test$BrokenGenericContainer.retrieve(Test.java:16) 
    at Test.main(Test.java:26) 

差異不大,它可能看起來,但與選中投的情況下,String成功地做了它的方式進入List<Integer>。在現實世界的應用中,這可能會導致嚴重的後果。在被檢查的演員的情況下,儘可能早地發現類型不匹配。


爲了避免未經檢查的強制轉換警告,@SuppressWarnings("unchecked")可以使用,如果程序員真的是肯定的方法,其實是安全的。更好的選擇是在可能的情況下使用泛型和檢查轉換。

由於約書亞·布洛克所言,

... unchecked警告是非常重要的。不要忽視它們。


爲了完整起見,this答案涉及Eclipse的細節。

相關問題