25

我有一个 ListView 列出了一个自定义对象(比如说MyObject)。

我想通过一个动态过滤它,所以我必须用一个 publishResults 方法EditText来实现一个:getFilter()

@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>

提前致谢!

4

4 回答 4

23

如果您所要做的只是 a Object,那么您无法在运行时检查您实际上是否拥有 a List<MyObject>,因为泛型类型MyObject仅用于编译时类型检查,它在运行时不可用。这就是为什么您在尝试添加instanceof检查时收到错误的原因。

如果您确定您的Object确实始终是 a,List<MyObject>那么我会说@SuppressWarnings没关系,如果您记录了为什么您确定这不是问题的原因。

但是,如果您绝对想避免警告,则可以创建自己的List实现(例如,MyObjectList),它本身不是通用的,而是实现List<MyObject>的。然后您可以在运行时进行instanceof检查。MyObjectList

另一种选择是按照错误提示进行检查并转换List<?>为。instanceof然后您可以遍历列表中的元素并检查它们是否实际上都是 MyObject 的所有实例,并将它们复制到一个新的List<MyObject>.

于 2013-02-01T09:38:20.647 回答
16

好吧,我终于设法找到了解决方案。

正如@Medo42 所说:

另一种选择是根据 instanceof 错误提示检查并转换为 List 。然后您可以遍历列表中的元素并检查它们是否实际上都是 MyObject 的实例,并将它们复制到一个新的列表中。

尽管我没有经历过创建一个全新对象的过程,以使这个特殊案例“无警告”地工作,但这是正确的方向。

所以我采用了@lokoko 的想法并在一个新setItems()方法中使用它,使用Object参数而不是 aList<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);
}

感谢大家的帮助!

于 2013-02-01T11:45:11.783 回答
15

尝试这样的事情:

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

filteredItems = tempList; // <-- set filtered
于 2013-02-01T10:34:13.677 回答
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
}
于 2013-02-01T09:37:07.120 回答