【问题标题】:Java generics not recognizing type?Java泛型不识别类型?
【发布时间】:2018-08-23 09:09:37
【问题描述】:

我有一个类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 扩展这个类,以便为这两个实现提供通用方法。

我的问题是当我传入 N 时,java 似乎无法将其识别为 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 实现之前,这段代码运行良好。

【问题讨论】:

  • 哪些行导致该错误?
  • 复制了您的代码。这里没有错误
  • 消息required: DoublyLinkedList got: Object 提示您在某处使用原始类型。
  • 尝试参数化基本类型并不是一个好主意
  • 错误源于我的驱动程序类,它使用 setPrev() 和 setNext() 方法,这取决于我使用的是 DoublyLinked 节点还是 FibonacciNode

标签: java generics data-structures


【解决方案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 实例,因为父类已经设置了类型约束。

【讨论】:

  • 您建议如何修复这个设计缺陷?拥有多个节点有什么问题?我只希望我的 Node 类具有属性 datanextprev 的 getter 和 setter。那么如何处理这些取决于ANodeBNode的实现。
【解决方案2】:

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

abstract class Node<N, T> {

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

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

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

你会发现 Node 只需要一个类型参数。 prevnext 字段可以是 Node&lt;T&gt; 类型:

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

    //... getters and setters
}

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

【讨论】:

  • 我以前有过这个。问题是 prev 和 next 不一定是节点。它们的类型为 FibonacciNodeDoublyLinkedNode
  • @BenjaminKosten 如果您的代码必须知道 FibonacciNode 和 DoublyLinkedNode 之间的区别,那么您的设计是错误的。
  • 嗯,谢谢,我没有这么想。你建议只使用 Node 类吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多