当前位置: 首页 > 知识库问答 >
问题:

如何克隆循环链表

安承教
2023-03-14

我试图克隆一个循环链表,就像你克隆一个单链表一样,但是我遇到了麻烦。

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

共有1个答案

王才英
2023-03-14

我认为问题在于:

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

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

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

使用该组合,super.clone()将抛出CloneNotBack的异常。这在html" target="_blank">javadoc中进行了解释。

但真正的问题是为什么要调用super.clone()

如果你这么做是因为超类有状态需要被复制到你正在创建的克隆中,那么它(超类)必须提供某种方式来克隆自己;即它需要执行上述操作之一...或者提供“复制构造器”或类似的东西。

如果你这样做只是为了打字,那么你应该这样做:

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

其中构造函数(如果需要,它可以<code>private</code>)创建一个实例,您可以开始填充该实例。请注意,这是类型安全的。

我注意到这一评论:

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

如果它的意思是总是这个类,那么只要修复它以匹配你实际做的事情。记住,只有当超类是可克隆的时候,你才能做到这一点…目前不是!

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

    < li >正如我所解释的,您不能在所有情况下都这样做。 < li >虽然有争论说使用另一种方法复制超类状态可能是不可取的,但在OO设计中,子类有权对其超类作出假设。 < li >此外,通过调用< code>super.clone()您是在做假设...那个< code>clone()会起作用的!
 类似资料:
  • 问题内容: 我有一个其中包含许多bufferedimages的对象,我想创建一个新对象,将所有bufferedimages复制到新对象中,但是这些新图像可能会更改,并且我不希望通过更改原始对象图像来更改新对象图像。 明白了吗? 这有可能做到吗,有人可以建议一个好方法吗?我曾经想到过getSubImage,但在某处阅读过,该子映像的任何更改都被重新关联回了父映像。 我只希望能够获得BufferedI

  • 问题内容: 我希望conda的根环境在另一个环境中复制所有软件包。如何才能做到这一点? 问题答案: 有一些选项可以将依赖项名称/ URL /版本复制到文件中。 建议 通常,在新环境中工作比更改环境更安全。但是,在尝试更改之前,请考虑备份现有环境。通过在演示环境中测试这些命令来验证所需的结果。例如,要备份您的环境: 选件 选项1 -YAML文件 在第二个环境(例如)中,将名称+导出到yaml文件:

  • 问题内容: 如何克隆 Java并同时在Java中克隆其项目? 例如,我有: 我希望其中的对象与狗列表中的对象不同。 问题答案: 你将需要迭代这些项目,然后逐个克隆它们,然后将克隆放入结果数组中。 显然,要使该方法起作用,你将必须使你的类实现接口并重写该方法。

  • 问题内容: 如果克隆数组,我将使用 我想知道如何在nodejs中克隆对象。 问题答案: 对于不需要压缩每一滴性能的实用程序和类,我经常作弊,只是使用JSON执行深层复制: 这不是唯一的答案,也不是最优雅的答案。所有其他答案都应考虑成为生产瓶颈。但是,这是一个快速而肮脏的解决方案,非常有效,并且在大多数情况下(我会克隆属性的简单哈希值)很有用。

  • 我想制作一份扩展的副本,作为我自己扩展的基础。我如何克隆一个TYPO3扩展,以同样的行为开始我自己的扩展。我必须更改哪些文件和参数?

  • 我已经在数据库中保存了一个JPA实体。 我想拥有它的副本(具有不同的id),并修改了一些字段。 最简单的方法是什么?例如: 将它的字段设置为并持久化它会起作用吗? 我是否必须为实体创建一个克隆方法(复制除之外的所有字段)? 还有其他方法吗(比如使用克隆框架)?