我正在尝试以克隆单链列表的方式来克隆循环链表,但是遇到了麻烦。
我试图只将调用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()返回空列表时,程序不会引发此异常。
答案 0 :(得分:0)
我认为这是问题所在
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),那完全是错误的:
super.clone()
,您正在假设clone()
可以工作!