对于未知类型转换列表的声明

时间:2018-04-20 14:28:19

标签: java generics casting

我试图在for循环

中自动将对象列表的每个元素转换为正确的类型
public boolean equals(Object obj) {
    if(obj == null || !(obj instanceof KGramPostingsEntry)) {
        return false;
    }
    KGramPostingsEntry other = (KGramPostingsEntry) obj;
    if(other.tokenID == this.tokenID) {
        return true;
    }
    return false;
}

正如我在代码中发布的那样," for statement"显示错误:

  

类型不匹配:无法转换元素类型捕获#1-of?到A

我尝试过其他解决方案:

class A {

}

class B {
  void sampleMethod() {
    List<?> l1 = //initialized somewhere;
    /* 
       I do know perfectly l1 got elements of Class A
       I just could not declare List<A> for other (generic types) reasons
    */
    for (A el: l1) { // Type mismatch: cannot convert from element type capture#1-of ? to A
      System.out.println(el);
    }
  }
}

现在警告结果:

  

类型安全:从列表到列表的未选中投射

最后,我找到了一个工作(但在我看来不合适)的解决方案,即在内部投射:

for (A el: (List<A>)l1)

为什么我不能在for语句中做这种投射?真的没办法干净利落吗?

3 个答案:

答案 0 :(得分:2)

  

真的没办法干净利落吗?

如果您使用通配符声明List

List<?> l1 = //initialized somewhere;

如果没有任何警告,你将无法将其元素强制转换为特定类型 你试图做的事情会破坏仿制药的目的。

您在评论中写道:

  

我无法为其他(通用类型)原因声明List<A>

没有通配符或绑定的泛型变量(如List<A>)有一些限制。众所周知,您无法为List<B>分配B,其中AList<? extends A>的子类。但是有另一种方法可以使它作为List<A>工作,同时它还有其他一些限制。

事实上,在声明A时,您没有描述遇到的问题。因此很难提供具体的解决方案 但我认为,如果仅操作列表中的List<A>个实例,则应声明更具体的类型。 因此,如果{{1}}导致代码出现问题,请深入研究此问题,如果“无法解析”,为什么不提出相关问题。

答案 1 :(得分:1)

如果以下内容,&#34;我确实知道l1得到了A类和#34;的元素,然后尝试:

List<?> l1 = ...

@SuppressWarnings("unchecked")
List<A> l2 = (List<A>) l1;

for (A a: l2) { ... }

但更简洁的方法是迭代原始列表,检查元素类型,然后在没有警告的情况下进行投射:

for (Object generic: l1) {
    if (generic instanceof A) {
        A a = (A) generic; // without warnings
        // do stuff
    } else if (generic == null) { // if nulls possible
        // do stuff
    } else {
        throw new IllegalArgumentException("item not of class A");
    }
}

答案 2 :(得分:0)

在循环中使用铸造元素的解决方案是完全合适的。 List<?>是未知列表,其元素类型与任何内容匹配。所以你唯一能确定的是所有项目都是对象,所以你这样做。这总是安全的,因为无论集合的实际类型如何,它都包含对象。您可以参考Oracle Generics tutorial中的类似案例,该案例被视为良好的代码示例。

希望它有所帮助!