2013-02-01 27 views
16

我有一個列表視圖列出了一個自定義對象(比如說MyObject)。類型安全:從對象到列表未選中投射<MyObject>

我想通過EditText動態過濾,所以我不得不實行getFilter()與publishResults方法:

@Override 
protected void publishResults(CharSequence constraint, FilterResults results) { 
    MyObjectAdapter.this.setItems((List<MyObject>) results.values); 
    MyObjectAdapter.this.notifyDataSetChanged(); 
} 

在這一點上,Eclipse的抱怨:Type safety: Unchecked cast from Object to List<MyObject>

我相信這個廣播將始終是真實的,但Eclipse只建議添加@SuppressWarnings("unchecked"),但我完全反對SuppressWarnings,因爲它只隱藏問題,而不是解決方案...

我嘗試添加:

if(results.values instanceof List<MyObject>) 

但是Eclipse再次抱怨了,這解決不了任何問題......

Cannot perform instanceof check against parameterized type List<MyObject>. Use the form List<?>

我知道鑄件永遠是正確的,但它是使有道代碼要確定results.values實際上是一個List<MyObject>

在此先感謝!

+0

http://stackoverflow.com/questions/262367/type-safety-unchecked-cast –

回答

8

好了,我終於找到一個解決方案。

正如@ Medo42說:

另一種方法是檢查並轉換爲列表作爲的instanceof 錯誤提示。然後你可以迭代列表中的元素並檢查它們是否實際上是MyObject的所有實例,並將它們複製到 一個新的列表中。

即使我沒有經過創建一個全新的對象的過程,爲了使這個特定的情況下工作「警告少」這是正確的方向去。

所以我把@lokoko的想法,並用它在新setItems()方法,與Object參數而不是List<MyObject>,以確保

結果代碼如下:

public void setItems(List<MyObject> var){ 
    this.list = var; 
} 

public void setItems(Object var){ 
    List<MyObject> result = new ArrayList<MyObject>(); 
    if (var instanceof List){ 
     for(int i = 0; i < ((List<?>)var).size(); i++){ 
      Object item = ((List<?>) var).get(i); 
      if(item instanceof MyObject){ 
       result.add((MyObject) item); 
      } 
     } 
    } 
    setItems(result); 
} 

感謝大家的幫助!

3

您可以在將其傳遞到setItems()之前執行檢查。

final Object myListObj = reuslts.values; 
if(myListObj instanceof List<?>) { 
    if(((List<?>)myListObj).get(0) instanceof MyObject) 
     // You can safely suppress the warning here because you made sure it is a List containing MyObject 
     MyObjectAdapter.this.setItems((List<? extends MyObject>) myListObj); 

} 

然而,需要相應地改變你的setItems()方法:

public void setItems(List<? extends MyObject> list) { 
    // Your code here 
} 
+0

這個檢查只確保列表中的* first *對象是一個'MyObject',所以你唯一顯示的是列表*可以*包含這些元素 - 而不是它實際上是一個'List '或者甚至是一個List?擴展MyObject>'。相反,你已經證明它是一個List <?超級MyObject>'。 – Medo42

+0

你是對的。但是,'List '不能包含'Integer'的元素?如果'MyObject'沒有子類,這個效果很好。即使'extends MyObject'中的對象,它們都包含必需的接口或函數,因爲方法簽名聲明瞭MyObject,而不是其他的子類。 –

+0

從技術上講,'List '*可以包含一個'Integer',因爲該列表的泛型類型在運行時不會被強制執行。但即使你有這種保證,即使「MyObject」沒有子類,你的建議也是無效的。想象一下'List '包含一個'MyObject'和一個String。你的支票會把它轉換成'List <?擴展MyObject>',因爲第一個元素碰巧是一個'MyObject',但試圖通過該流行列表獲取第二個元素將導致'ClassCastException'。 – Medo42

17

如果你必須從工作是Object,那麼你就不能在運行時檢查你確實有一個List<MyObject> ,因爲通用類型MyObject僅用於編譯時類型檢查,所以在運行時可以使用而不是。這就是爲什麼當您嘗試添加instanceof檢查時出現錯誤。

如果你確定你真的Object總是List<MyObject>那麼我想說的是@SuppressWarnings OK,如果你說明爲什麼你肯定是沒有問題的。

如果您絕對想要避免警告,您可以創建自己的List實現(例如,MyObjectList),該實現不是通用的,而是實現List<MyObject>。然後,您可以在運行時對MyObjectList執行instanceof檢查。

另一種選擇是檢查並轉換爲List<?>,因爲instanceof錯誤提示。然後,您可以迭代列表中的元素,並檢查它們是否實際上是MyObject的所有實例,並將它們複製到新的List<MyObject>

9

嘗試是這樣的:

List<?> result = (List<?>) results.values; 
for (Object object : result) { 
    if (object instanceof MyObject) { 
     tempList.add((MyObject) object); // <-- add to temp 
    } 
} 

filteredItems = tempList; // <-- set filtered 
+0

你的解決方案幫助我弄清楚如何解決我的問題,thx! –

相關問題