Java泛型自我引用:它安全吗?

2022-09-03 06:41:48

我有这个简单的界面:

public interface Node<E extends Node<E>>
{
    public E getParent();

    public List<E> getChildren();

    default List<E> listNodes()
    {
        List<E> result = new ArrayList<>();

        // ------> is this always safe? <-----
        @SuppressWarnings("unchecked")
        E root = (E) this;

        Queue<E> queue = new ArrayDeque<>();
        queue.add(root);

        while(!queue.isEmpty())
        {
            E node = queue.remove();

            result.add(node);

            queue.addAll(node.getChildren());
        }

        return result;
    }
}

我看到这总是(根据定义)的一个实例。
但是我无法想象一个案例不是一个实例...
既然 ,难道不应该也等同于定义??thisNode<E>thisEE extends Node<E>Node<E>E

你能举一个对象的例子,它是 的实例,但它不是 ?的实例?Node<E>E

与此同时,我的大脑正在融化...


前面的类是一个简化的示例。
为了说明为什么我需要一个自绑定,我增加了一些复杂性:

public interface Node<E extends Node<E, R>, R extends NodeRelation<E>>
{
    public List<R> getParents();

    public List<R> getChildren();

    default List<E> listDescendants()
    {
        List<E> result = new ArrayList<>();

        @SuppressWarnings("unchecked")
        E root = (E) this;

        Queue<E> queue = new ArrayDeque<>();
        queue.add(root);

        while(!queue.isEmpty())
        {
            E node = queue.remove();

            result.add(node);

            node.getChildren()
                .stream()
                .map(NodeRelation::getChild)
                .forEach(queue::add);
        }

        return result;
    }
}

public interface NodeRelation<E>
{
    public E getParent();

    public E getChild();
}

答案 1

一个简单的例子来说明这个问题:一个不同类型的节点的节点:

class NodeA implements Node<NodeA> {
    ...
}

和:

class NodeB implements Node<NodeA> {
    ...
}

在本例中,将解析为 ,其中 是 .这是不相容的。E root = (E) thisNodeA root = (NodeA) thisthisNodeB


答案 2

如果没有 ,则可能具有以下任一情况:<E extends Node<E>>

Node<Integer>

其中泛型类型根本不是 a,或者Node

Node<DifferentNode>

其中通用边界不匹配。

也就是说,以这种方式看到边界并不典型,因为预期是包含某种类型值的节点,并且将是 一个 ,而不是一个 。Node<E>EchildrenList<Node<E>>List<E>