我试图以克隆单个链接列表的相同方式克隆一个循环链接列表,但是遇到了麻烦。
我试图只在公共方法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()
将抛出CloneNotSupportedException
。 javadoc中对此进行了说明。真正的问题是,为什么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/