Java中的级联泛型类型声明

时间:2017-05-17 22:05:17

标签: java arrays generics arraylist nested-generics

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

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()返回节点的内容,而不是节点本身,但我无法弄清楚如何。

我认为由Graph泛型定义的Node泛型意味着Node类总是与Graph类具有相同的类型。那不是这样吗?

Node类看起来像

public class Node<E> {

    private LinkedList<Edge> edges;
    private E obj;

    public E getObject() {
        return obj;
    }

    // other useful stuff
} 

感谢您的帮助!

编辑:现在需要的只是使返回的数组成为正确的类型。有没有办法从具有泛型类型赋值的ArrayList中获取数组?

2 个答案:

答案 0 :(得分:1)

您需要在getThings方法中使用某种形式的E具体化。

如果要保留getThings的签名,可以添加construtor参数以提供实际的类E。使用该类,您可以创建一个数组以传递给toArray(E[])

List<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);
}

答案 1 :(得分:1)

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

此代码可解决此问题。我或多或少地从他们的toArray(E[] a)函数的ArrayList源代码中解除了逻辑(当然它的部分内容被删除了。)

@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源代码,以便看到一些更进一步的逻辑,并以线程安全的方式完成相同的任务。