Java 中的级联泛型类型声明

Cascading Generic Type declarations in Java

如果这是一个常见问题,我很难在任何地方找到它,但我正在处理本质上是级联类型的问题。

public class Graph<E> {

    private LinkedList<Node<E>> nodes;

    public Graph() {
        this.nodes = new LinkedList<>();
    }

    public E[] getNodes() {
        ArrayList<E> list = new ArrayList<>();
        for (Node<E> node : nodes)
            list.add(node.getObject());
        return list.toArray(new E[0]); // any way to make this line work?
    }

    // other important stuff
}

我想做这样的事情,但是我不能用这种方式实例化通用数组。其中 getNodes() returns 节点的内容,而不是节点本身,但我不知道如何。

我在想由 Graph 泛型定义的 Node 泛型将意味着 Node class 始终与 Graph class 具有相同的类型。不是这样吗?

节点 class 看起来像

public class Node<E> {

    private LinkedList<Edge> edges;
    private E obj;

    public E getObject() {
        return obj;
    }

    // other useful stuff
} 

感谢您的帮助!

编辑:现在所需要做的就是使返回的数组具有正确的类型。有没有办法从具有泛型类型分配的 ArrayList 中获取数组?

您需要在 getThings 方法中对 E 进行某种形式的具体化。

如果你想保持 getThings 的签名不变,你可以添加一个构造函数参数来提供实际的 class E。使用那个 class 你可以创建一个数组传递给 List<E>

toArray(E[]) 方法
private final Class<E> type;
private final List<E> list;

public CustomClass(Class<E> type) {
    this.type = type;
    this.list = new ArrayList<>();
}

@SuppressWarnings("unchecked")
public E[] getThings() {
    Object[] reference = (Object[]) Array.newInstance(type, list.size());
    return (E[]) list.toArray(reference);
}

其他人提出了一个无效的答案,但给了我一个最终有效的想法,但他们也把它放在了问题的评论部分,所以我会在这里重申并回答我自己的问题。

这段代码可以解决问题。我或多或少地从 ArrayList 源代码中提取了他们的 toArray(E[] a) 函数的逻辑(当然其中的一些内容被删掉了)。

@SuppressWarnings("unchecked")
public E[] getNodes(E[] a) {
    int size = nodes.size();
    // creates an empty array of the right size and type
    E[] arr =(E[]) java.lang.reflect.Array
            .newInstance(a.getClass().getComponentType(), size);
    // fills that array with the correct data
    for (int i = 0; i < size; i++)
        arr[i] = nodes.get(i).getObject();
    return arr;
}

查看 ArrayList 源代码,以了解更进一步的一些逻辑,并以线程安全的方式完成相同的任务。