2

The Java documentation says:

A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.

Invoking Object's clone method on an instance that does not implement the Cloneable interface results in the exception CloneNotSupportedException being thrown.

By convention, classes that implement this interface should override Object.clone (which is protected) with a public method. See Object.clone() for details on overriding this method.

Note that this interface does not contain the clone method. Therefore, it is not possible to clone an object merely by virtue of the fact that it implements this interface. Even if the clone method is invoked reflectively, there is no guarantee that it will succeed.

And I have this UserProfile class:

public class UserProfile implements Cloneable { private String name; private int ssn; private String address; public UserProfile(String name, int ssn, String address) { this.name = name; this.ssn = ssn; this.address = address; } public UserProfile(UserProfile user) { this.name = user.getName(); this.ssn = user.getSSN(); this.address = user.getAddress(); } // get methods here... @Override public UserProfile clone() { return new UserProfile(this); } } 

And for testing porpuses, I do this in main():

UserProfile up1 = new UserProfile("User", 123, "Street"); UserProfile up2 = up1.clone(); 

So far, no problems compiling/running. Now, per my understanding of the documentation, removing implements Cloneable from the UserProfile class should throw an exception in up1.clone() call, but it doesn't.

I've read around here that the Cloneable interface is broken but I don't really know what that means. Am I missing something?

2
  • 1
    Cloneable is problematic as the Cloneable interface has no clone() method, you either need to know the specific type that implements the clone() method (in which case you the concrete type, so you could use the copy constructor instead) or you have to use reflection. Any API that requires reflection to work properly could be described as broken. Commented May 22, 2010 at 16:03
  • Be careful : in clone method, don't call a constructor, but call (UserProfile)super.clone(). See java.sun.com/javase/6/docs/api/java/lang/… "By convention..." Commented May 22, 2010 at 18:09

3 Answers 3

5

Now, per my understanding of the documentation, removing implements Cloneable from the UserProfile class should throw and exception in up1.clone() call, but it doesn't.

As long as your class still has an implementation of the clone() method, an exception will ofcourse not be thrown when you call it - it works just like any other method, there's no special magic involved.

The implementation of clone() in class Object is what throws the exception, but you've overridden that method.

Sign up to request clarification or add additional context in comments.

2 Comments

At least some magic is involved, because Object.clone() won't throw that exception when called via super.clone(). But apart from that, I agree.
Object.clone() checks if the object is an instance of a class that implements Cloneable and throws the exception if it isn't. No special magic (for example special handling by the compiler) necessary...
1

It means that if you implements Cloneable and omit the clone() method and THEN call the clone() method, an exception will be thrown.

EDIT: It has been mentioned probably 1 billion times before, but

DON'T USE THE CLONE METHOD!

If you need cloning functionality, provide a copy constructor instead.

The interface is called broken because it doesn't force you to implement clone() (which it should).

4 Comments

What's the argument for not using the clone method if I override it with my own implementation?
IMHO just implementing a copy constructor may lead to other problems with respect to inheritance. I can't see why one should be worse than the other. And in that case, why not stick with the standard Cloneable? At least most developpers know about its shortcomings and can handle them.
As far as I can see it, I'm overriding the clone method in my class and all it does is call the copy constructor. What's the problem in that?
@Nazgulled Sry, didn't see the copy constructor. But why doesn't your clone method just call super.clone()?
1

I agree with both answers and add something: the interface is like a 'tag' to say that your class implements clone(). That's useful in api-like methods when you don't know the object type. Then you can write

if (myobj instanceof Cloneable) { dosmthng(); } 

1 Comment

You should use instanceof instead of is.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.