I'm attempting to clone a circularly linked list in the same way you clone a singularly linked list, but am having trouble.
I've attempted leaving just the line calling the protected method of clone() in the public method clone(), but the program still throws the error.
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;
}
This code works while using singly linked lists. The expected output is the linked list printed twice, but the actual output is the exception thrown "CloneNotSupported". Note that the program doesn't throw this exception when clone() returns a null list.
Here is the problem, I think:
CircularlyLinkedList<E> other = (CircularlyLinkedList<E>) super.clone();
Now you haven't told us what the superclass of CircularlyLinkedList
is, but the evidence is that:
Cloneable
marker interface.clone
method that it inherits from Object
.With that combination, super.clone()
will throw CloneNotSupportedException
. This is explained in the javadoc.
The real issue though is why are you calling super.clone()
?
If you are doing it because the superclass has state that needs to be copied in the clone you are creating, then it (the superclass) must provide some way of cloning itself; i.e. it needs to do one of the above ... or provide a "copy constructor" or similar.
If you are doing it just to make the typing work, then you should probably do something like this:
CircularlyLinkedList<E> other = new CircularlyLinkedList<>();
where the constructor (which can private
if necessary) creates an instance that you can start filling in. Note that this is type-safe.
I note this comment:
// always use inherited Object.clone() to create the initial copy
If it is intended to mean always for this class, then just fix it to match what you actually do. Bearing in mind that you can only if the superclass is cloneable ... which it currently isn't!
If it is intended to record that it is "best practice" (or something; see this) to do this in all cases, that is simply wrong:
super.clone()
you are making an assumption ... that clone()
will work!