【问题标题】:How to Clone a Circularly Linked List如何克隆循环链接列表
【发布时间】:2019-06-17 14:07:26
【问题描述】:

我正在尝试以与克隆单向链表相同的方式克隆循环链表,但遇到了麻烦。

我试图在公共方法clone()中只留下调用受保护方法clone()的行,但程序仍然抛出错误。

public static void main(String[] args) throws CloneNotSupportedException 
  {

  CircularlyLinkedList<String> circularList = new 
  CircularlyLinkedList<String>();
  circularList.addFirst("1");
  circularList.addLast("2");
  circularList.addLast("3");
  circularList.addLast("4");


  CircularlyLinkedList<String> newList = new CircularlyLinkedList<String>();
  newList= circularList.clone();
  System.out.println(newList);
  }
@SuppressWarnings("unchecked")
public CircularlyLinkedList<E> clone() throws CloneNotSupportedException 
{
  // always use inherited Object.clone() to create the initial copy
    CircularlyLinkedList<E> other = (CircularlyLinkedList<E>) super.clone(); // safe cast
    if (size > 0) {                    // we need independent chain of nodes
        other.head = new Node<>(head.getElement(), null);
        Node<E> walk = head.getNext();      // walk through remainder of original list
        Node<E> otherTail = other.head;     // remember most recently created node
        while (walk != null) {              // make a new node storing same element
          Node<E> newest = new Node<>(walk.getElement(), null);
          otherTail.setNext(newest);     // link previous node to this one
          otherTail = newest;
          walk = walk.getNext();
        }
      }
    return other;

}

此代码在使用单链表时有效。预期输出是打印两次的链表,但实际输出是抛出的异常“CloneNotSupported”。请注意,当 clone() 返回空列表时,程序不会抛出此异常。

【问题讨论】:

    标签: java linked-list clone singly-linked-list


    【解决方案1】:

    我认为这是问题所在:

    CircularlyLinkedList<E> other = (CircularlyLinkedList<E>) super.clone(); 
    

    现在你还没有告诉我们CircularlyLinkedList 的超类是什么,但证据是:

    1. 它没有实现Cloneable 标记接口。
    2. 它不会覆盖从Object 继承的clone 方法。

    使用该组合,super.clone() 将抛出 CloneNotSupportedException。这在javadoc 中有解释。


    真正的问题是你为什么打电话给super.clone()

    如果您这样做是因为超类具有需要在您创建的克隆中复制的状态,那么它(超类)必须提供某种克隆方式;即它需要执行上述操作之一......或提供“复制构造函数”或类似的。

    如果您这样做只是为了让打字工作,那么您可能应该这样做:

        CircularlyLinkedList<E> other = new CircularlyLinkedList<>(); 
    

    构造函数(如果需要可以private)创建一个实例,您可以开始填写。注意这是类型安全的。


    我注意到这条评论:

    // always use inherited Object.clone() to create the initial copy
    

    如果它的意思是总是用于这个类,那么只需修复它以匹配你实际所做的。请记住,只有在超类是可克隆的情况下您才可以……目前还不能!

    如果打算记录在所有情况下都这样做是“最佳实践”(或其他东西;参见this),那是完全错误的:

    • 正如我所解释的,您不能在所有情况下都这样做。
    • 虽然有人认为使用其他方法来复制超类状态可能是不可取的,但子类有权在 OO 设计中对其超类做出假设。
    • 此外,通过调用super.clone(),您假设...clone() 会起作用!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多