如何克隆循环链表
How to Clone a Circularly Linked List
我正在尝试以与克隆单向链表相同的方式克隆循环链表,但遇到了问题。
我试图在 public 方法 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() returns 一个空列表时,程序不会抛出此异常。
这里是问题所在,我认为:
CircularlyLinkedList<E> other = (CircularlyLinkedList<E>) super.clone();
现在你还没有告诉我们 CircularlyLinkedList
的 superclass 是什么,但证据是:
- 它没有实现
Cloneable
标记接口。
- 它不会覆盖它继承自
Object
的 clone
方法。
使用该组合,super.clone()
将抛出 CloneNotSupportedException
。 javadoc.
中对此进行了解释
但真正的问题是你为什么打电话给 super.clone()
?
如果你这样做是因为 superclass 的状态需要复制到你正在创建的克隆中,那么它(superclass)必须提供某种克隆自身的方法;即它需要执行上述操作之一......或提供 "copy constructor" 或类似的。
如果您这样做只是为了让打字工作,那么您可能应该这样做:
CircularlyLinkedList<E> other = new CircularlyLinkedList<>();
其中构造函数(如有必要,可以 private
创建一个实例,您可以开始填写该实例。请注意,这是类型安全的。
我注意到这条评论:
// always use inherited Object.clone() to create the initial copy
如果它的意思是 always for this class,那么只需修改它以匹配您的实际操作。请记住,只有当 superclass 是可克隆的时,您才可以……目前它不是!
如果要记录在所有情况下都"best practice"(或其他;参见this)这样做,那是完全错误的:
- 正如我所解释的,您不能在所有情况下都这样做。
- 虽然有人认为使用另一种方法来复制 superclass 状态可能是不可取的,但 subclass 有权在 OO 中对其 superclass 进行假设设计。
- 此外,通过调用
super.clone()
,您是在假设......clone()
会起作用!
我正在尝试以与克隆单向链表相同的方式克隆循环链表,但遇到了问题。
我试图在 public 方法 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() returns 一个空列表时,程序不会抛出此异常。
这里是问题所在,我认为:
CircularlyLinkedList<E> other = (CircularlyLinkedList<E>) super.clone();
现在你还没有告诉我们 CircularlyLinkedList
的 superclass 是什么,但证据是:
- 它没有实现
Cloneable
标记接口。 - 它不会覆盖它继承自
Object
的clone
方法。
使用该组合,super.clone()
将抛出 CloneNotSupportedException
。 javadoc.
但真正的问题是你为什么打电话给 super.clone()
?
如果你这样做是因为 superclass 的状态需要复制到你正在创建的克隆中,那么它(superclass)必须提供某种克隆自身的方法;即它需要执行上述操作之一......或提供 "copy constructor" 或类似的。
如果您这样做只是为了让打字工作,那么您可能应该这样做:
CircularlyLinkedList<E> other = new CircularlyLinkedList<>();
其中构造函数(如有必要,可以 private
创建一个实例,您可以开始填写该实例。请注意,这是类型安全的。
我注意到这条评论:
// always use inherited Object.clone() to create the initial copy
如果它的意思是 always for this class,那么只需修改它以匹配您的实际操作。请记住,只有当 superclass 是可克隆的时,您才可以……目前它不是!
如果要记录在所有情况下都"best practice"(或其他;参见this)这样做,那是完全错误的:
- 正如我所解释的,您不能在所有情况下都这样做。
- 虽然有人认为使用另一种方法来复制 superclass 状态可能是不可取的,但 subclass 有权在 OO 中对其 superclass 进行假设设计。
- 此外,通过调用
super.clone()
,您是在假设......clone()
会起作用!