0

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

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
} 

谢谢你的帮助!

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

4

2 回答 2

1

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

如果你想保持getThings原样的签名,你可以添加一个构造函数参数来提供实际的 class 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);
}
于 2017-05-17T22:24:04.373 回答
1

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

这段代码可以解决这个问题。我或多或少地从 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 源代码,以了解一些更进一步并以同样是线程安全的方式完成相同任务的逻辑。

于 2017-05-19T00:52:58.960 回答