2009-10-21 56 views
2

我正在執行List實施。正因爲如此,我必須覆蓋的方法如何避免重寫集合的方法中未經檢查的強制轉換?

Collection.containsAll(Collection<?> c); 
Collection.removeAll(Collection<?> c); 
Collection.retainAll(Collection<?> c); 

但是因爲它是解釋by Sun,他們接受與收藏任何類型的內容(注意<?>)。所以這個集合不會被編譯器檢查,而是由我自己來檢查它。但怎麼做呢?由於類型擦除,每個元素上的instanceof將不起作用。下一個解決方案是將每個元素都投射到ClassCastException。看這裏:

public boolean containsAll(Collection<?> c) { 
    boolean foundAll = true; 
    for (Object element : c) { 
     try { 
      foundAll &= this.contains((T) element); 
     } catch (ClassCastException e) { 
      foundAll = false; 
     } 
    } 
    return foundAll; 
} 

其他兩種方法看起來相似。這樣可行。但它給了我編譯器警告「警告:[unchecked] unchecked cast」!除非我用「@SuppressWarnings("unchecked")」來壓制它,否則它將無法正常編譯。

我不想依靠「@SuppressWarnings("unchecked")」,除非我真的必須。有沒有辦法避免它?你將如何實現像containsAll(Collection<?> c)那樣的方法?

編輯

好了,對不起你們,我不太清楚。我不擴展AbstractList,我不想。我的列表是通過一個平衡的二叉樹實現的。我有自己的執行insert(),remove(),(實際上是搜索葉)等,並且都採用(通用)類型的參數T。關鍵目標是擁有一個可以在迭代時修改的排序列表。

那麼...我如何避免containsAll(Collection <?>)的警告?我必須投!

謝謝! craesh

+2

btw:只要foundAll是假的,你應該從你的循環中突破,否則你會做不必要的工作。實際上,你可以完全擺脫布爾標誌。 – 2009-10-21 12:15:09

+0

哇,我從來沒見過&=操作符。謝謝! – 2009-10-21 12:54:07

+0

@Joachim:謝謝,這是一個好主意! @matt:我很少使用它,但有時它非常有用;) – craesh 2009-10-21 13:41:56

回答

9

你不需要當你調用,因爲它被定義爲boolean contains(Object o)你的元素轉換爲T。請注意,您可以詢問Collection<String>是否和Integer對象。沒有必要的鑄造。

remove()也需要Object,所以根本不需要鑄造。

並順便說一句:擴展AbstractList帶走了實施List的大部分無聊工作。

+0

對AbstractList提示+1,我傾向於忘記那一個 – Abel 2009-10-21 12:15:11

+0

對不起,我的錯:我簡化了這個例子太多了。在這種情況下,元素將在contains()中被鑄造。我有一個包含(T元素)的方法,我稱這一個,但沒有發佈它。 – craesh 2009-10-21 13:38:50

+0

@craesh:你也可以提供這些,但如果你實現'List'接口,那麼你可以簡單地調用這些方法的非通用版本。 – 2009-10-21 14:03:41

2

只是爲了澄清一個誤解仿製藥:每個元素

的instanceof不會因爲類型擦除工作。

不,這是不正確的。 instanceof工作得很好。 「類型刪除」意味着你無法獲得編譯時間類型,該類型是通過泛型爲泛型聲明的 - 但是你不關心這一點。

你想要檢查的是你正在獲取的元素的運行時類型。這是通過instanceof完成的,完全獨立於泛型,並且可以工作。

當然,作爲約阿希姆·紹爾指出的那樣,你甚至不需要檢查的類型在這個特定的情況下,這樣的點是沒有實際意義呢?

編輯:

由於事實上,Java的AbstractCollection就是這樣的:

public boolean containsAll(Collection<?> c) { 
    Iterator<?> e = c.iterator(); 
    while (e.hasNext()) 
    if(!contains(e.next())) 
     return false; 
    return true; 
} 

(來自Sun的JDK源代碼)。

那麼你真的應該嘗試從AbstractList或至少AbstractCollections

0
當然可以的

延伸AbstractList爲了得到這些方法無繼承,但你也可以遍歷this,而不是c

@Override 
public boolean containsAll(Collection<?> c) { 
    Iterator<T> it = this.iterator(); 

    while (it.hasNext()) { 
     if (!c.contains(it.next())) { 
      return false; 
     } 
    } 

    return true; 
} 

或者乾脆:

@Override 
public boolean containsAll(Collection<?> c) { 
    for (Object o : this) { 
     if (!c.contains(o)) { 
      return false; 
     } 
    } 

    return true; 
} 
+0

謝謝,但在我的情況下,這是沒有選擇。我的應用程序中我的列表可能包含多達10k個元素。我有一個二進制搜索,所以在我的列表中搜索比在迭代中搜索更快。 – craesh 2009-10-21 14:23:27

0

如果你不想擴展AbstractList,至少擴展AbstractCollection。那麼你根本不需要實現這個方法,問題是沒有意義的。

相關問題