【问题标题】:Difficulty with generic for-each loop通用 for-each 循环的困难
【发布时间】:2015-07-03 12:46:10
【问题描述】:

我无法编译一个 foreach 循环。我很确定这是我的泛型处理的问题,因为错误是对象兼容性问题。我已经搜索了解决方案,但找不到任何解决问题的方法。

这是定义 Iterable adjList 的代码。

public class Graph<V,E> { 
    private SinglyLinkedList<Vertex<V>> vertices = new SinglyLinkedList<>();
    protected class Vertex<V> {
        private SinglyLinkedList<Edge<E>> adjList = new SinglyLinkedList<>();
        public void addEdge(Edge<E> e) {adjList.addLast(e);}  
        public Iterable<Edge<E>> adjList() {
            return (SinglyLinkedList<Edge<E>>) adjList;
        }
    }
    public Iterable<Edge<E>> edges(Vertex<V> v) {
        return v.adjList;
    //... Edge<E> is also a nested class
    public Iterable<Vertex<V>> vertices() {return vertices;}
}

adjList 实际上是可迭代的,因为 SinglyLinkedList 是:

public class SinglyLinkedList<T> implements Iterable<T> {
    //... 
    private class ListIterator implements Iterator<T> {
    // ... next(), hasNext()
    }
    public Iterator<T> iterator() {return new ListIterator();}
}

此迭代器在其他情况下也可以正常工作,包括其他 foreach 循环。这是它不起作用的地方(来自不同类的主要方法):

Graph<String, Integer> testgraph = createGraph("testgraph.txt");
//createGraph add some vertices and edges to testgraph
for (Vertex v : testgraph.vertices()) { 
    for (Edge e : testgraph.edges(v)) {   //<--- problem here
            System.out.print(e.getElement());
        }       
    }
}

错误是“不兼容的类型:对象无法转换为 Graph.Edge。”

问题: 为什么 testgraph.edges(v) 返回的是对象列表而不是边缘?我真的很茫然。

还有,

for (Edge e : v.adjList()) 

也不起作用,出现相同的错误,并且在 Edge 之后的菱形括号中添加“Integer”也无法编译。这确实有效,但我真的想避免这种可怕的演员阵容:

for (Edge e : ((Graph<String,Integer>.Vertex<String>)v).adjList())    

非常感谢您的任何想法。

【问题讨论】:

  • 您没有向我们展示所有代码并没有帮助 - 但基本上问题在于您使用的是原始类型。如果您可以缩短一个简短但完整的程序(使用vertices() 等)会有所帮助。
  • 好的。我会尝试添加相关代码。您介意指出原始类型在哪里吗?我想我明白它们是什么,但我认为我在任何地方都使用了菱形括号。
  • 您使用的是VertexEdge,而不是(比如说)Vertex&lt;String&gt;Edge&lt;Integer&gt;
  • 如果 Vertex 和 Edge 是 Graph 的内部类,对它们进行参数化有些多余。也许您打算制作 Vertex 和 Edge static 类。
  • @Misha 或者您可以从VertexEdge 中删除类型参数,以便它们使用VE 定义的Graph。您的静态类解决方案还需要添加E 作为adjList 的返回类型的类型参数才能工作。无论哪种方式,我们都需要更多代码来正确识别问题的根源。 :-)

标签: java generics foreach iterable


【解决方案1】:

您正在使用 VertexEdge 没有任何参数化,使它们有效地 Vertex&lt;Object&gt;Edge&lt;Object&gt;

public Iterable<Edge<E>> edges(Vertex<V> v) {
    return v.adjList;
}

EdgeVertex 都期望指定 Type

for (Edge<Integer> e : ((Graph<String,Integer>.Vertex<String>)v).adjList())  

以上内容不是 可怕的演员表,它们是泛型所期望的类型。

你有两个选择:

要么在任何地方指定类型,要么在任何地方不指定它们,完全删除它们。

【讨论】:

    【解决方案2】:

    问题是您将Vertex&lt;V&gt;Edge&lt;E&gt; 声明为Graph&lt;V,E&gt; 的内部类。这意味着Vertex 的每个实例都与参数化类Graph 的实例相关联。因此,当您尝试在Graph 实例之外编写Vertex&lt;Integer&gt; 时,这意味着Graph.Vertex&lt;Integer&gt; 用于Graph 的原始类型。这就是编译器抱怨的原因。

    您的选择是:

    1. Vertex&lt;V&gt;Edge&lt;E&gt; 类声明为static。然后你就可以写Vertex&lt;String&gt;Edge&lt;Integer&gt;
    2. VertexEdge 中删除类型参数并将它们称为Graph&lt;String,Integer&gt;.VertexGraph&lt;String,Integer&gt;.Edge

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-12
      • 1970-01-01
      • 2016-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多