Java array cloning strange behavior - java

I'm trying to clone an instance of a custom class I made called CSP. I have one instance called csp and I want to make a clone of csp called cspclone. Here is what I'm using to do that:
CSP cspclone = new CSP((csp.x).clone(), (csp.d).clone(), (csp.c).clone());
For some reason though when I pass cspclone to a method that modifies it csp gets modified also as if I forgot the .clone() functions but I didn't! Why is this happening?!

Override the clone method in CSP:
public class CSP {
private String aField;
private int[] array;
private int[][] twoDArr;
private List<ALContent> list; //here ALContent also needs to override clone properly
#Override
public Object clone() {
CSP clone = new CSP();
clone.aField = this.aField;
clone.array = new int[this.array.length];
System.arraycopy(this.array, 0, clone.array, 0, this.array.length);
clone.list = new ArrayList<ALContent>();
for(ALContent content : this.list) {
clone.list.add(content.clone()); //make sure you add the clone of the content
}
clone.twoDArr = new int[this.twoDArr.length][];
for(int i=0; i<this.twoDArr.length; i++) {
clone.twoDArr[i] = new int[this.twoDArr[i].length];
System.arraycopy(this.twoDArr[i], 0, clone.twoDArr[i], 0, this.twoDArr[i].length);
}
return clone;
}
}
Then you can do:
CSP csp = new CSP();
CSP cspClone = (CSP) csp.clone();

If your properties of array type use System.arraycopy

According to http://download.oracle.com/javase/1.3/docs/api/java/lang/Object.html#clone%28%29
this method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned. Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.
You might have to override the clone method and clone() a reference type attribute within the object (i.e., perform deep copy operation).

To solve your problem you need deep cloning. The default clone method does a shallow copy. See Object.clone().
Here are some approaches. All have advantages and drawbacks.
Override: Override the clone() method.
Serialization: Write the object to a stream and a read it back from the stream.
Reflection: Here is a tutorial on reflection.
Use a deep close library, such as Java Deep-Cloning library.
Here are several other stackoverflow discussions of cloning.
Java: recommended solution for deep cloning/copying an instance
Deep clone utility recomendation
How to clone ArrayList and also clone its contents?

Related

Copy Constructor vs Cloneable. Why shouldn't I consider Cloneable?

I was reading this answer and he mentioned a link, where author explains why shouldn't we use Cloneable. But, still have doubt what was stated there
If I have an array of Cloneable, you would think that I could run down
that array and clone every element to make a deep copy of the array,
but I can't. You can not cast something to Cloneable and call the clone
method, because Cloneable doesn't have a public clone method and
neither does Object. If you try to cast to Cloneable and call the
clone method, the compiler will say you are trying to call the
protected clone method on object.
But, here I did
Init s = Init.getInstance(); // getting instance
int count=0;
Cloneable[] v = new Cloneable[5]; // creating array
Init x = s;
Init y = new Init(s);
try {
while (count < 5) {
v[count++] = (Cloneable) s.clone(); // casting it.
}
s.setClassName("Example");
System.out.println(((Init) v[2]).getClassName()); // Displaying.
} catch (CloneNotSupportedException ex) {
ex.printStackTrace();
}
I was able to create Cloneable array and I did what author said will cause error Or Did I misunderstood author statement ? Anyone, please help me to understand the reason to choose Copy Constructor over Cloneable.
You are not casting s to Cloneable and then calling clone() on it.
Instead you are calling s.clone() and then casting the result to Clonable.
You are able to do this because s is of type Init and Init has public clone() method.
Do this instead and you will find the compiler shouting,
v[count++] = ((Cloneable) s).clone();
Now let's say you want to clone an array (You obviously only know it's a Cloneable array. Which means you don't know it's actual Type.
Cloneable[] cloneArray = new Cloneable[5];
cloneArray[i] = new Init(); // Let's say it's initialized with different type objects but all `Cloneable`.
for (Cloneable object : cloneArray) {
object.clone(); // Compiler wont allow it. And you don't know what type it is.
}
So, you basically cannot deep clone a Cloneable array.

How to deep copy [duplicate]

This question already has answers here:
How do I copy an object in Java?
(23 answers)
Closed 9 years ago.
I am having difficulties understanding the concept of "deep copy" in Java.
Assuming I had a class "myClass" with various parameters in it. I tried writing a method "copy" which was supposed to return a deep copy of such class as:
public myClass copy() {
myClass deepCopy = new myClass();
deepCopy.varA = varA;
deepCopy.varB = varB;
return deepCopy;
}
Can somebody confirm whether this is indeed "deep copying" or if I am doing something wrong?
Thanks!
If you don’t want to implement deep copy yourselves then you can go for serialization. It does implements deep copy implicitly and gracefully handling cyclic dependencies.
A nice article about Deep Copy, Clone and Shallow Copy can be found here.
Only If:
Class "myClass" only contains varA and varB.
Class "myClass" has no superclass.
Variables varA and varB are of an elementary type (ie. String, int, long, ....). Otherwise you'll have to apply the same copying process to them too.
In deep copy When the copied object contains some other object its references are copied recursively
see more at here
A deep copy occurs when an object is copied along with the objects to which it refers.
If suppose there is a MainObject1 of MainObject type having fields "field1" of int type, and "ContainObject1" of ContainObject type. When you do a deep copy of MainObject1, MainObject2 is created with "field3" containing the copied value of "field1" and "ContainObject2" containing the copied value of ContainObject1. So any changes made to ContainObject1 in MainObject1 will not be reflected in MainObject2.
In your implementation, if you are trying to simulate deep copy, then you should have only these two variables : varA and varB in your class of primitive type.
This would only be a deep copy if varA and VarB were primitive types. If they are reference types than your new object will point at the same instances of these classes as the original.
An easy way to implement deep copy is via serialization. Apache commons lang provides a utility method for this (SerializationUtils.clone( foo ) ).
It does however requires that all the objects are serializable.
If this is not the case for you XStream can be used for deep cloning with minimal development effort.
http://x-stream.github.io/
Observe output of following program.
1> See output without clone() method. Remove clone() method from following program. (example of shallow copy)
2> See output with clone() method. (Example Deep copy. See ArrayList object's output)
import java.util.ArrayList;
import java.util.List;
public class DeepCopy implements Cloneable {
private List<String> hobbiesList;
private int age;
private String name;
private float salary;
public static void main(String[] args) throws CloneNotSupportedException {
DeepCopy original = new DeepCopy();
original.name="AAA";
original.age=20;
original.salary=10000;
original.hobbiesList = new ArrayList<String>();
original.hobbiesList.add("Cricket");
original.hobbiesList.add("Movies");
original.hobbiesList.add("Guitar");
original.hobbiesList.add("Eating");
DeepCopy cloned = (DeepCopy) original.clone();
System.out.println("original:="+original);
System.out.println("cloned :="+cloned);
System.out.println("After adding two more hobbies in 'original' which untimately reflected in 'cloned'");
cloned.name="BBB";
cloned.age=27;
cloned.salary=18237;
cloned.hobbiesList.add("Trecking");
System.out.println("original :="+original);
System.out.println("cloned changed:="+cloned);
}
#Override
protected Object clone() throws CloneNotSupportedException {
DeepCopy clone = (DeepCopy)super.clone();
clone.hobbiesList = new ArrayList<String>(clone.hobbiesList);
return clone;
}
#Override
public String toString() {
return "My name is (String)"+name + " having age (int)"+age+". I earned (float)"+salary+" and hobbies are (ArrayList)"+hobbiesList;
}
}

Difference between creating an object using new keyword and using clone method

What is the difference between creating an object using the new keyword and creating an object using clone()? Is there any difference between memory allocation?
new creates an object according to the constructor, while clone() creates a new object and initializes the fields with the contents of the original object.
I take it, you read the javadoc, so let me take you through an example:
public class MyBaby implements Cloneable {
int age = 0;
String name = "Dolly";
List<String> list = new ArrayList<String>();
public static void main(String[] args) {
MyBaby originalBaby = new MyBaby();
originalBaby.setAge(1);
try {
// We clone the baby.
MyBaby clonedBaby = (MyBaby) originalBaby.clone();
// both babies now have: age 1, name "Molly" and an empty arraylist
originalBaby.setAge(2);
// originalBaby has age 2, the clone has age 1
originalBaby.setName("Molly");
// same goes for the String, both are individual fields
originalBaby.getList().add("addedString");
// both babies get the string added to the list,
// because both point to the same list.
System.out.println(clonedBaby.toString());
}
catch (CloneNotSupportedException e) {}
}
}
The javadoc says:
this method performs a "shallow copy" of this object, not a "deep
copy" operation.
which explains the behaviour of our babies' list: References are copied, not the elements that are referenced, thus our copy is "shallow"
The memory allocation can differ of course:
you can initialize fields in your constructor
clone can initialize a field, i.e. an array
new operator instantiates the new object while clone() is more like a copy constructor. clone() method creates a copy of the object with values of member attributes also copied.
Simple stated,
new creates an instance
while
clone returns a clone of an instance.
Clone() creates a new instance of the same class and copies all the fields to the new instance and returns it (shallow copying).
while the new keyword is a Java operator that creates the object ( http://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html ).
new() construcion of object as per default constructor.
clone() does shallow copy of references.
We should use clone only when the cost of object creation is high and we would rather clone and set the behaviour.

copy enum array

Hi I have a enum array and it is a field of my class. And I am implementing clone method of this class. But I have some ideas about copying array of enums but what is the formal way of copying an enum array ?
public enum StateEnum {
START, PLAY, PAUSE , STOP
}
class MyClass{
StateEnum[] stateEnums;
public Object clone(){
MyClass copyClass = new MyClass();
// copy enums
}
}
Enum values are (or should be) immutable, so you don't need to copy them.
You can just make a shallow copy of the array by calling System.arraycopy().
As said by SLaks, use the System.arraycopy to clone your array. Further, the
MyClass copyClass = new MyClass();
should be replaced by
MyClass copyClass = (MyClass)super.clone();
The reason for this is explained in this article in full detail, where the end of page 2 discusses the common pitfalls while implementing a clone method

If you don't clone in Java then what do you do and what do you call it?

Does anyone have any suggested or established best practices and naming conventions for copy constructors / factory methods etc in Java? In particular, say I have a class Thing and I want a method somewhere that returns a new Thing with the same value as a Thing passed in (or as the instance if it's an instance method). Would you have this as constructor or a static factory method or instance method? What would you call it?
As per the title, I want to avoid clone() and Cloneable.
Effective Java recommends either of the following:
A copy constructor (as noted by others):
public Item(Item item)
A copy factory method:
public static Item newInstance(Item item)
(Also, no copying for immutables)
The primary difference is that with #1 you choose the actual class of the result, and with #2 the implementer can return a subclass. The semantics of the class may guide you into which one is best.
I would call it a copy method or a copy constructor (as the case may be). If it was a static method, then I would call it a factory.
In terms of what to do, the most flexible and long living option is a copy constructor. This gives subclasses the ability to copy themselves just like the parent.
I'd do a constructor
...
public Thing(Thing copyFrom)
{
attr1 = copyFrom.attr1;
attr2 = copyFrom.attr2;
//etc...
}
then when you want to clone it
Thing copy = new Thing(copy from me);
You can overwrite the clone()-method, if you want. Another used practice is a constructor, that takes an object of this type, i.e. new ArrayList(anotherList).
You've got a few options, implement Cloneable, add a copy constructor but my preferred way is to use a method (static or instance) that has a name which is descriptive of what the copy operation is doing - is it a deep or shallow copy, etc.
Use immutable data structures. The only reason you feel that you need clone() is that you're mutating your objects in place. Stop doing that. Think about how you can:
Make your classes final.
Make fields in your classes final and private.
For example, here's a "setter" for an immutable 3D vector object:
public Vector3D setX(double x) {
return new Vector3D(x, this.y, this.z);
}
So I guess what I'm saying is... I use copy constructors instead of mutation, and I just name them according to the attribute that I want to modify.
Another option is to implement the copying method in the source object, e.g.:
interface Has3DCoords {
void setLocation(double x, double y, double z);
void copyCoordsTo(Has3DCoords dest);
}
You would then implement copying with a piece of code like:
class Thing implements Has3DCoords {
private Point3D loc;
// ...
void setLocation(double x, double y, double z) {
loc.setLocation(x, y, z);
// or: loc = new Point3D(x, y, z);
}
void copyCoordsTo(Has3DCoords dest) {
loc.copyCoordsTo(dest);
// or: dest.setLocation(loc.getX(), loc.getY(), loc.getZ());
}
OtherThing createOtherThing() {
OtherThing result = new OtherThing();
this.copyCoordsTo(result);
return result;
}
}
This can be useful if:
It does not make sense to clone the whole object
There is a group of related properties that are often copied as one unit
You do not want to expose loc as a property of Thing
The number of properties is large (or there are many such groups) so a constructor that required all of them as parameters would be unwieldy.
This is not the nicest approach to copying objects but the following is sometimes useful if you wish to perform a deep copy of a Serializable object. This avoids having to write copy constuctors, implement Cloneable or writing factory classes.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
//Serializes the input object
oos.writeObject(input);
ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
//Copy of the input object
Object output = ois.readObject();
Don't forget to handle the exceptions and to close the streams nicely.

Categories