我试图以克隆单个链接列表的相同方式克隆一个循环链接列表,但是遇到了麻烦。

我试图只在公共方法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()返回空列表时,程序不会引发此异常。

最佳答案

我认为这是问题所在:

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


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


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


通过这种组合,super.clone()将抛出CloneNotSupportedExceptionjavadoc中对此进行了说明。



真正的问题是,为什么ypou呼叫super.clone()

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

如果您只是为了使键入工作而这样做,那么您可能应该执行以下操作:

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


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



我注意到此评论:

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


如果打算总是针对此类,则只需对其进行修复以使其与您的实际工作相匹配。请记住,只有超类是可克隆的,您才可以……而当前不是!

如果要记录在所有情况下都是这样做的“最佳实践”(或某些方法;请参见this),那完全是错误的:


正如我所解释的,您不能在所有情况下都做到这一点。
尽管有观点认为不建议使用另一种方法来复制超类状态,但子类有权在OO设计中对其超类做出假设。
此外,通过调用super.clone(),您正在假设... clone()将起作用!

关于java - 如何克隆循环链接列表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54336478/

10-11 22:29
查看更多