Java泛型无法识别类型?

时间:2018-08-23 09:09:38

标签: java generics data-structures

我有一个类Node,它是DoublyLinkedNodeFibonacciNode的抽象类。

package com.benjamin;

abstract class Node<N, T extends Comparable<T>> {
    private N prev;
    private N next;
    private T data;

    public N getPrev() { return prev; }
    public N getNext() { return next; }
    public T getData() { return data; }

    public void setPrev(N prev) { this.prev = prev; }
    public void setNext(N next) { this.next = next; }
    public void setData(T data) { this.data = data; }
}

DoublyLinkedNodeFibonacciNode扩展了此类,以为这两种实现提供通用方法。

我的问题是,当我传入Java时,java似乎无法将N的类型识别为DoublyLinkedList

package com.benjamin;

public class DoublyLinkedNode<T extends Comparable<T>> extends Node<DoublyLinkedNode<T>, T>{
    DoublyLinkedNode() {
        setPrev(this);
        setNext(this);
        setData(null);
    }

    DoublyLinkedNode(T data) {
        setData(data);
    }

    @Override
    public String toString() {
        if(getData() != null) {
            return "| " + getData().toString() + " |";
        }
        else {
            return "| ; |";
        }
    }
}

在我的DoublyLinkedList课堂上,我收到一条错误消息,说unable to resolve method setPrev(),在许多地方,我得到了required: DoublyLinkedList got: Object

在我决定统一Node的实现之前,这段代码运行良好。

2 个答案:

答案 0 :(得分:1)

似乎期望ANode.getNext()ANode.getPrev()严格返回类型为ANode的实例(而不是类型为BNodeCNode等的实例) )。如果是,则将执行以下操作:

abstract class Node<N extends Node<N, T>, T extends Comparable<T>> {}

class ANode<T extends Comparable<T>> extends Node<ANode<T>, T> {}
class BNode<T extends Comparable<T>> extends Node<BNode<T>, T> {}
class CNode<T extends Comparable<T>> extends Node<CNode<T>, T> {}

但是,正如this comment中指出的那样,该设计将导致以下问题:

class DNode<T extends Comparable<T>> extends ANode<T> {}
class ENode<T extends Comparable<T>> extends ANode<T> {}

在这些情况下,DNode/ENode.getNext()/getPrev()将返回ANode实例,因为父类已经设置了类型约束。

答案 1 :(得分:0)

您的设计问题似乎源于N中的Node类型参数。为了简单起见,我们首先删除Comparable内容:

abstract class Node<N, T> {

现在,如果我们愿意,可以将DoublyLinkedNode定义为

class DoublyLinkedNode<T> extends Node<String, T>{

第一个类型参数是String,因此我们的prevnext字段都是字符串。那有意义吗?不,绝对不是。链中的下一个节点也必须是一个节点。

您会发现Node确实只需要一个类型参数。 prevnext字段的类型可以为Node<T>

abstract class Node<T> {
    private Node<T> prev;
    private Node<T> next;
    private T data;

    //... getters and setters
}

setPrevsetNext都设置为this似乎也很奇怪。我很容易看到这导致您的程序陷入无限循环。