I am trying to implement a clone() method on a DoubleLinkedList. Now, the problem is that implementing it by "the convention" is a lot more troublesome than just creating a new DoubleLinkedList and filling it with all the elements of my current DoubleLinkedList.
Is there any inconvenient I am not seeing when doing that?
Here is my current approach:
#Override
public DoubleLinkedList<T> clone() {
DoubleLinkedList<T> dll = new DoubleLinkedList<T>();
for (T element : dll) {
dll.add(element);
}
return dll;
}
Here is what it would be by the convention:
#Override
public DoubleLinkedList<T> clone() {
try {
DoubleLinkedList<T> dll = (DoubleLinkedList<T>)super.clone();
//kinda complex code to copy elements
return dll;
} catch (CloneNotSupportedException e) {
throw new InternalError(e.toString());
}
}
As you correctly point out, the convention is to always call super.clone() in the beginning of an implementation of clone(). From the API docs on Object#clone():
By convention, the returned object should be obtained by calling super.clone. If a class and all of its superclasses (except Object) obey this convention, it will be the case that x.clone().getClass() == x.getClass().
Your first attempt (without using super.clone()) has the following problem:
Suppose I have
class IntDoubleLinkedList extends DoubleLinkedList<Integer> implements Cloneable
(and that IntDoubleLinkedList does not bother to override clone()) and I run the following code:
IntDoubleLinkedList idll = new IntDoubleLinkedList();
IntDoubleLinkedList idll2 = (IntDoubleLinkedList) idll.clone();
What will happen? The clone method of your DoubleLinkedList will be executed, which, if it doesn't go through super.clone(), returns an instance of DoubleLinkedList which in turn can not be casted to an IntDoubleLinkedList. A ClassCastException will be thrown!
So how does super.clone() solve this issue? Well, if everybody stick to the convention of calling super.clone() in an overriden clone method, Object.clone() will eventually be called, and this implementation will create an instance of a proper type (IntDoubleLinkedList in this case)!
As others have explained, if you're going to override clone you should obey its contract.
If you like the way you currently have it, just make DoubleLinkedList not Cloneable and turn your implementation into a copy constructor or static factory method. A static factory method has the added benefit of providing a bit of type inferencing for generic type arguments, too.
P.S. LinkedList is a doubly-linked list.
If you do it by creating a new list and adding all the elements from the source, if you then do something like:
DoubleLinkedList<Foo> l1 = new DoubleLinkedList<Foo>();
l1.add (new Foo(params));
DoubleLinkedList<Foo> l2 = l1.clone();
Foo foo = l2.get(0);
foo.setProperty("new Value");
foo.property will be "new value" in both lists (the same the other way around; if you change it in l1, changes will appear in l2). The correct way would be to actually clone every element and the add the clone to ensure the lists are independent. Take note that this only happens if you change properties of the elements, not if you add, move, delete them from the list.
Edit: just realized that since it's a linked list, the next/previous elements are properties of the element, so even adding, deleting, will affect both list.
The reason the "convention" is to call super.clone() is to ensure the ultimate type of the cloned object matches the object that is being cloned. For example if you instantiate your own new DoubleLinkedList in the clone() method, well that's nice for now, but later if a subclass fails to override clone() it will end up returning a clone that is a DoubleLinkedList instead of its own class. (It'll also fail to clone its additional fields, if any, probably! so there are larger issues.)
In that sense, the conventional method is preferred, and it is indeed clunky.
Both implementations, however, have a similar problem: you're not deep-copying the data structures. The clone is only a shallow cop. This is probably not what the caller expects. You would need to go through and replace each value in the DoubleLinkedList with a clone of the value, and likewise for other non-primitive fields.
In that sense, the conventional method is going to give the wrong result here! You need a third way. Your first method probably just about works, except that you need to add element.clone() for example.
Related
I am working on a JDK6 project.
I have a pojo like:
public class MyPojo implements serializable {
private List<Integer> ids;
public List<Integers> getIds() {
return ids;
}
public List<Integers> setIds(List<Integer> ids) {
// idsCopy = copy of ids; // how can I do it?
this.ids = idsCopy;
}
}
I'd like to store a copy of the parameter ids passed in the setter, but I don't want to specialize it in the setId method signature by declaring the reference as a particular implementation of the List interface: depending on where the pojo is used, ids could be either a LinkedList, or an ArrayList, etc.
I'd like to keep the same implementation of the ids parameter.
How can I do the copy?
The first thing I thought was: ids.getClass().newInstance(), but it needs to be surrounded by a try/catch block for InstantiationException and IllegalAccessException, in particular because I am not sure that the actual implementation of ids has an empty constructor. Is there something more immediate?
Update
In this case the most common, straightforward and reasonable thing to do is avoiding making a copy and let who will use the class MyPojo passing a copy of the object to set, for instance:
List<Integer> ls = new Arraylist<>();
MyPojo pj = new MyPojo();
pj.setIds(ls.clone()); // or using copy constructor or anything else..
At the beginning I had the idea to do like this:
public <T extends List<Integer> & Cloneable> void setIds(T ids) {
this.ids = ids.clone();
}
enforcing using a class implementing also Cloneable but the javadoc of Cloneable interface explains very good why this is not intended to work (and also why reflection on clone would not too):
A class implements the Cloneable interface to
indicate to the 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 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.
At the end, regardless the context, the answer to my question
Is there something more immediate?
is "no", most probably because there should not be the need to do it...
..even though..
https://rules.sonarsource.com/java/type/Vulnerability/RSPEC-2384
Is there something more immediate?
There are two possible ways to do this:
The method you proposed: use reflection to invoke the no-args constructor create a new empty list, and then use List::addAll to copy the elements to the new list.
Use the Object::clone method to create the copy.
Either approach (if it works!) will create a list object of the same type as the original. But neither method is guaranteed to work for all possible List classes.
The reflective approach fails if the list implementation class has no usable / accessible no-args constructor.
The clone approach fails if the list implementation class doesn't override Object::clone appropriately.
Note that these are not hypothetical concerns. A list implementation class may be deliberately designed to prevent programs making clones of the list. For example, there may be some relationship between the list and (say) a database query result set, such that cloning makes no sense.
But the flip-side is that if the library designer didn't provide a no-args constructor or a clone override, they probably did it for a good reason.
Finally, it is questionable that you should be trying to do this at all. There is no obvious reason for your MyPojo classes ids property to use the same List class as the original argument. This is actually making the behavior MyPojo class dependent on the behavior of the supplied list. I would argue that this is a bad thing because you are weakening the abstraction boundary for your MyPojo class.
As you have said it yourself:
The first thing I thought was: ids.getClass().newInstance(), but it
needs to be surrounded by a try/catch block for InstantiationException
and IllegalAccessException, in particular because I am not sure that
the actual implementation of ids has an empty constructor. Is there
something more immediate?
How will you be able to construct an instance of the underlying class when you don't even know what the constructor looks like? Say through reflection, you know what a (there could be more than one) constructor looks like, you still have to worry about things like:
Private vs Internal/Package-Private vs Public - How do you handle each case? Some implementations of List such as the ones found in the guava library use the builder pattern to construct the collection and therefore make the constructor private.
Number of constructor arguments - If more than one, how do you construct the rest?
Exceptions thrown by the constructor - How do you catch them all? Don't say "catch Exception" because you may miss Throwable.
Multiple constructors - How do you decide which one to call?
Many more corner cases to deal with...
You should adopt the KISS (Keep It Simple Soldier) principle as well as the SoC (Separation of Concerns) principle. Keep it simple and you will be rewarded. Let the person using the Pojo decide how they want to retrieve the list. As long as you make it clear (through documentation) what the method does, it is up to the user to make rational decisions as to how they use that method.
If they do something like:
LinkedList<Integer> myIds = ...;
myPojo.setIds(myIds);
then let them decide how to retrieve the ids; They can either cast the returned type or make a copy.
If you made it clear in the documentation that the list is copied, then the person using this POJO should know to make a copy as a LinkedList when they retrieve it, otherwise it should be safe for them to cast the list to a LinkedList.
I would still argue that even the above is not simple enough. The simplest thing to do (and this is what is widely accepted) is to use the most general type for the work needed. If you need a Mapping type, use Map, not HashMap or List/Set of tuples; If you need a unique collection, use Set, if you need a general collection, use List, etc.
You can use Arrays.asList for that e.g.
public void setIds(List<Integer> ids) {
this.ids = Arrays.asList(ids.toArray(new Integer[ids.size()]));
}
this should work for Java 1.6
I know this question has been asked so many times.
First of all Object.clone() method in java is native method i.e. it is implemented in JVM and user doesn't need to know about it's implementation.
My question is whether this method is abstract too. If not why it has to be overridden in the class that we want to clone.
And one more question .
It is overridden as follows
public Object clone() {
MyClass obj;
try {
obj = (MyClass)super.clone();
} catch(CloneNotSupportedException e) {
Statements
}
return obj;
}
In the 4th line of this code we called , super.clone() method , which clone() method are we calling in this line and if Object.clone() method why did we override it , we can simply cast it wherever we want to clone the Object like
MyClass obj2 = (MyClass)obj1.clone();
and is their any way to know the coding of Object.clone() method?
A method cannot be native and abstract at the same time because native is a statement about a specific implementation of a method;
clone must be overridden at least because Object#clone is protected to prevent access to clients in the case the object does not support cloning;
in many cases clone needs to do more than Object#clone, which just makes a binary copy of the original, which amounts to a shallow clone, with all the referenced objects staying the same;
there's no point in catching CloneNotSupportedException in the subclass: you should already know whether the superclass does or doesn't support cloning (it is not something which can change at runtime).
Object.clone() is not abstract. Overriding it when implementing Clonable is just a convention. (Clonable is a marker interface - like Serializable etc.)
Overriding methods (should) always call Object.clone() directly or indirectly.
I think, casting it is not necessary because Object.clone() preserves the exact class. If you catch the CloneNotSupportedException you could even return MyClass.
As Object.clone() is implemented natively you would have to look at the sources of some JVM implementation like OpenJDK.
My question is whether it's abstract too
No it isn't, and the Javadoc already tells you that, as does the fact that Object itself isn't abstract, and it 'doesn't have to be overridden in the class we want to clone' unless you want to change the access permission, which has nothing to do with 'abstract': and you couldn't call 'super.clone()' in such an override unless it wasn't abstract.
In short, your question doesn't make much sense.
I am trying to ask if a list contains a certain string.
public void searchList(Scanner scan, Object list){
System.out.println("Search for element:\t");
String p = scan.nextLine();
if (list.contains(p))
System.out.println(p + " is in the list");
else
System.out.println(p + " is not in the list.");
}
I am getting:
Prog7Methods.java:23: cannot find symbol
symbol : method contains(java.lang.String)
location: class java.lang.Object
if (list.contains(p))
I do not understand! I have imported java.io.* and java.util.* how does it not recognize this?
You need to declare the list as a List. Instead of
public void searchList(Scanner scan, Object list){
use
public void searchList(Scanner scan, List list){
or even better:
public void searchList(Scanner scan, List<String> list){
Because there is no Object.contains() method. Your method signature should probably be (Scanner, List) not (Scanner, Object)
list is a Object and Object does not have contains method. You need to cast it to a List first to call contains method. Or, you can change the method signature to receive a List.
Take a moment to study an Object. All Java classes are a subclass of Object, and so all Java classes inherit the methods clone(), equals(), finalize(), hashCode(), and so on.
contains() is not in that list of Object methods. contains() comes from a different place -- an interface called Collection. An interface defines a contract for some class (and all classes are ultimately Objects), that contract being a list of methods that must be implemented. Collection defines a contains() method, and everything that implements a Collection interface, including any List-implementing class, must provide a contains() method.
When you provide a list to your searchList() method, you are passing it through an Object parameter. That means that within searchList(), the only methods that can be called are the ones defined for Object, even if the list in your call to searchList() really is a list of some sort. In a sense, your parameter list has "scrubbed out" the list-i-ness of the list parameter.
What you should do, as mentioned already, is change your parameter to Collection or List. That way, within your searchList() method, the Java compiler knows that the "list" parameter is really a List, and so really has a contains() method.
Note that List is also an interface, and it incorporates the Collection interface by extending it. So every class that implements the List interface must provide the methods in Collection, as well as the additional List methods. Should you use List or Collection? My opinion is to use the least constraining choice. It seems like your searchList() only uses contains(), so really, it will work on anything that implements Collection, including, for example, Set.
So I would rename your method from referring to where you are looking (inside of a list) to what you are looking for (the nextline).
public void searchForNextLine(Scanner scan, Collection lines){
System.out.println("Search for element:\t");
String p = scan.nextLine();
if (lines.contains(p))
System.out.println(p + " is in the collection of lines");
else
System.out.println(p + " is not in the collection of lines.");
}
Now let's say you've implemented your list with an ArrayList. Later you change your mind, deciding that a TreeSet is better. This searchForNextLine() method will continue to work, because both TreeSet and ArrayList are implementations of Collection. Better yet, if you decide to roll your own list class (and are sure that you want an actual List, and not some other sort of Collection), then as long as you implement the List interface, you'll be compelled to provide a contains() method (because you'll also be implementing the Collection interface as part of implementing the List interface), and you can pass object of your new class to searchForNextLine(), confident that it will work perfectly fine without any changes at all.
public class MyListClass<T> implements List<T> {
// all the methods required to implement a List interface
}
list is an Object not a List. If you think it is a LinkedList then change the method signature. If not, make a cast but do an instanceof.
Error output of compiler is quite clear. Your list variable is not List type but Object. Object has no method "contains".
Change
Object list
to
List<String> list
or (Java 1.4 and older)
List list
I would like to know the following:
Cloneable means we can have a clone or a copy of objects, by
implementing the Cloneable interface. What are the advantages and
disadvantages of doing that?
How does the recursive cloning happen if the object is a
composite object?
The first thing you should know about Cloneable is - don't use it.
It is very hard to implement cloning with Cloneable right, and the effort is not worth it.
Instead of that use some other options, like apache-commons SerializationUtils (deep-clone) or BeanUtils (shallow-clone), or simply use a copy-constructor.
See here for the views of Josh Bloch about cloning with Cloneable, which explains the many drawbacks of the approach. (Joshua Bloch was a Sun employee, and led the development of numerous Java features.)
Cloneable itself is unfortunately just a marker-interface, that is: it does not define the clone() method.
What is does, is change the behavior of the protected Object.clone() method, which will throw a CloneNotSupportedException for classes that do not implement Cloneable, and perform a member-wise shallow copy for classes that do.
Even if this is the behavior you are looking for, you'll still need to implement your own clone() method in order to make it public.
When implementing your own clone(), the idea is to start with the object create by super.clone(), which is guaranteed to be of the correct class, and then do any additional population of fields in case a shallow copy is not what you want. Calling a constructor from clone() would be problematic as this would break inheritance in case a subclass wants to add its own additional cloneable logic; if it were to call super.clone() it would get an object of the wrong class in this case.
This approach bypasses any logic that may be defined in your constructors though, which could potentially be problematic.
Another problem is that any subclasses that forget to override clone() will automatically inherit the default shallow copy, which is likely not what you want in case of mutable state (which will now be shared between the source and the copy).
Most developers don't use Cloneable for these reasons, and simply implement a copy constructor instead.
For more information and potential pitfalls of Cloneable, I highly recommend the book Effective Java by Joshua Bloch
Cloning invokes an extra-linguistic way of constructing objects - without constructors.
Cloning requires you to treat somehow with CloneNotSupportedException - or to bother client code for treating it.
Benefits are small - you just don't have to manually write a copying constructor.
So, use Cloneable judiciously. It doesn't give you sufficient benefits in comparison with the effort you need to apply to do everything right.
Cloning is a basic programming paradigm. The fact that Java may have implemented it poorly in many ways does not at all diminish the need for cloning. And, it is easy to implement cloning that will work however you want it to work, shallow, deep, mixed, whatever. You can even use the name clone for the function and not implement Cloneable if you like.
Suppose I have classes A, B, and C, where B and C are derived from A. If I have a list of objects of type A like this:
ArrayList<A> list1;
Now, that list can contains objects of type A, B, or C. You don't know what type the objects are. So, you can't copy the list like this:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
list2.add(new A(a));
}
If the object is actually of type B or C, you will not get the right copy. And, what if A is abstract? Now, some people have suggested this:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
if(a instanceof A) {
list2.add(new A(a));
} else if(a instanceof B) {
list2.add(new B(a));
} else if(a instanceof C) {
list2.add(new C(a));
}
}
This is a very, very bad idea. What if you add a new derived type? What if B or C are in another package and you don't have access to them in this class?
What you would like to do is this:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
list2.add(a.clone());
}
Lots of people have indicated why the basic Java implementation of clone is problematic. But, it's easily overcome this way:
In class A:
public A clone() {
return new A(this);
}
In class B:
#Override
public B clone() {
return new B(this);
}
In class C:
#Override
public C clone() {
return new C(this):
}
I'm not implementing Cloneable, just using the same function name. If you don't like that, name it something else.
A) There are not a whole lot of advantages of clone over a copy constructor. Probably the biggest one is the ability to create a new object of the exact same dynamic type (assuming the declared type is clonable and has a public clone method).
B) The default clone creates a shallow copy, and it will remain a shallow copy unless your clone implementation changes that. This can be difficult, especially if your class has final fields
Bozho is right, clone can be difficult to get right. A copy constructor/factory will serve most needs.
What are disadvantages of Cloneable?
Cloning is very dangerous if the object whom you are copying has composition.You need to think about below possible side effect in this case because clone creates shallow copy:
Let say you have one object to handle db related manipulation. Say, that object has Connection object as one of the property.
So when someone creates clone of originalObject, The object being created, let say, cloneObject.
Here the originalObject and cloneObject hold the same reference for Connection object.
Let say originalObject closes the Connection object, so now the cloneObject will not work because the connection object was shared between them and it was actaually closed by the originalObject.
Similar problem may occur if let say you want to clone a object which has IOStream as a property.
How does the recursive cloning happen if the object is a composite object?
Cloneable performs shallow copy. Meaning is that data of original object and clone object will point to the same reference/memory.
contrary in the case of deep copy, data from memory of original object is copied to the memory of clone object.
If I have a class:
public class MyType
{
private List<Integer> data;
private boolean someFlag;
public MyType(List<Integer> myData, boolean myFlag)
{
this.data = myData;
this.myFlag = someFlag;
}
}
Now, if I create an instance of MyType, how do I do a deep copy of it? I don't want the new object to point to the old reference, but an entirely new instance.
Is this a case when I should implement the Cloneable interface, or is that a used for shallow copies?
I can't just do:
MyType instance1 = new MyType(someData, false);
MyType instance2 = new MyType(instance1.getData(), instance1.getFlag());
I'm concerned about new instances of MyType pointing to the same reference for its "data" variable. So I need to copy it entirely.
So, if I have an existing object:
MyType someVar = new MyType(someList, false);
// Now, I want a copy of someVar, not another variable pointing to the same reference.
Can someone point me in the right direction?
First: Your code sample has some naming issues: is it myFlag or someFlag?
Many developers will abstain from Cloneable and just create a copy constructor for a class when deep copies are needed:
public class MyType {
private boolean myFlag;
private List<Integer> myList;
public MyType(MyType myInstance) {
myFlag = myInstance.myFlag;
myList = new ArrayList<Integer>(myInstance.myList);
}
}
Copy constructors quite common, and can be found in many of the Collections implementations. I prefer them over implementing Cloneable for reasons of clarity. It's also worth noting that even the mighty Joshua Bloch says in Effective Java (second edition page 61) that copy constructors have many advantages over Cloneable/clone.
They don't rely on a risk-prone
extralinguistic object creation
mechanism
They don't demand unenforceable
adherence to thinly documented
conventions
They don't conflict with the proper
use of final fields
They don't throw unnecessary checked
exceptions
They don't require casts.
If you don't own his book, get it!
You can make all classes in your object graph implement Cloneable and provide manual cloning. Since in your case it's only one list (i.e. a very small object graph), you'd better use the copy-constructor:
List newData = new ArrayList(data)
But remember that in that case the contents of the list will still be the same objects, so it won't be a real deep copy. In your case these are Integers, so no big deal. But if you change it, be careful.
If you need to clone bigger object graphs, then, in two steps:
make your class implement the Serializable interface
use apache commons-lang SerializationUtils.clone(yourObject)
It makes a deep copy using the serialization mechanisms in java.
Alternatively, you can use this library - it does not require the Serializable interface and makes deep copies using reflection.
You should implement Cloneable. You define what a "copy of your type" exactly means. Sometimes it is required to have a type containing a field whose content remains the same within multiple copies (==reference to the same object in all copied instances)
You have to take care on your own that all the fields are actually copied to a new instance. Primitive datatypes like int, long, etc. are copied as they are directly stored, they never contain references.
If you have fields to object references of what type ever, you need to find a mechanism to create a copy of each of them.
Generally, you do have a shallow copy after calling .clone(). If (and only if) all the types used in your class are themselves implementing Cloneable correctly, you get a fully recursive deep copy.
According to JavaDoc (Object.clone()) Clonable means the following:
x.clone() != x && x.clone().getClass() == x.getClass() && x.clone().equals(x)
Remember that this is the general intent, and this is not a mandatory contract
your class MyType must implement Cloneable. then you can call someVar.clone()
Implement ICloneable