通用for-each循环的难度

时间:2015-04-24 19:05:22

标签: java generics foreach iterable

我在编译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());
        }       
    }
}

错误是&#34;不兼容的类型:对象无法转换为Graph.Edge。&#34;

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

此外,

for (Edge e : v.adjList()) 

也没有工作,有相同的错误,并且添加&#34;整数&#34;在Edge之后的菱形括号中也没有编译。这确实有效,但我真的想避免这种可怕的演员阵容:

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

非常感谢任何想法。

2 个答案:

答案 0 :(得分:2)

您正在使用VertexEdge而没有任何参数化,从而有效地Vertex<Object>Edge<Object>

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

EdgeVertex都希望指定Type

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

以上是 可怕的演员,它们是泛型预期的类型。

您有两种选择:

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

答案 1 :(得分:0)

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

您的选择是:

  1. 将类Vertex<V>Edge<E>声明为static。然后,您就可以撰写Vertex<String>Edge<Integer>
  2. VertexEdge删除类型参数,并将其称为Graph<String,Integer>.VertexGraph<String,Integer>.Edge