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

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.

Related

copy of object (JAVA)

I am trying to make a copy of an object to make some tests on it without affecting the original object. I made this copy() function but the original object is still affected.
Inside the class "I" I have this copy function:
#Override
public Piece copy() {
I newPiece = new I(blocks[0], blocks[1], blocks[2], blocks[3]);
newPiece.STATUS = this.STATUS;
newPiece.FORM = this.FORM;
return newPiece;
}
and I try to make a copy like this:
Piece rotated = piece.copy();
rotated.changeForm();
Class "I" is a subclass of the abstract class Piece with the abstract method copy(). when I do the changeForm() in the copied object it affects the original one too.
SOLVED
the Block objects were passed as reference too so I needed to add a copy() method even for the type Block. Code changed this way:
#Override
public Piece copy() {
I newPiece=new I(blocks[0].copy(),blocks[1].copy(),blocks[2].copy(),blocks[3].copy());
newPiece.STATUS=this.STATUS;
newPiece.FORM=this.FORM;
return newPiece;
}
Every type of Piece attributes or fields that is not a primitive type should be copied too.
So the values of STATUS, blocks[1], blocks[2], blocks[3] and FORM.
I hope it helps.
If the contents of blocks are reference types, you will also have to copy them.
Alternatively you could just make a new constructor for Piece and use it.
Piece newPiece = new Piece(oldPiece.thing1(), oldPiece.thing2().....);
This is the problem, in your copy constructor:
Piece rotated=piece.copy();
That's just copying the reference to the Piece. Both objects will still refer to the same object.
You can use:
Piece rotated = new Piece(piece.copy());
You're not changing the new object, you're changing its contents. Unfortunately, the original object has the same contents, so it appears as though you had done something to the original object.
You have made what is called a shallow copy. It would appear that you need to make a deep copy, which involves making copies of the contents of the original object. In your case, you need to make a copy of blocks[0], blocks[1], etc.
The question that may haunt you is how deep that copy must be. You will no doubt find out, but you may have to go deeper than it would appear at first.
As previous authors mention you should make a deep copy of object, but with your code you're only making a shallow copy.
The fastest and easiest way to deep copy an object in java is to serialize() it and deserialize().
Assuming all your classes implement java.io.Serializable interface:
public static <T extends Serializable> T copy(T orig) {
T obj = null;
try {
// Write the object out to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(orig);
out.flush();
out.close();
// Make an input stream from the byte array and read
// a copy of the object back in.
ObjectInputStream in = new ObjectInputStream(
new ByteArrayInputStream(bos.toByteArray()));
obj = (T) in.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
return obj;
}

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.

Java array cloning strange behavior

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?

Call a method of class using object of some other class in java

List CreateNewStatements(ForLoop L)
{
List stmts = new ArrayList();
FlatIterator iter = new FlatIterator(L.getBody());
Traversable t1 = null;
LoopUnroll l = new LoopUnroll(t1);
while(iter.hasNext())
{
stmts.add(iter.next().clone());
}
return stmts;
}
The above code is giving the error as "The method clone() from the type Object is not visible".
In the above code, iter.next() returns a statement(Eg. fx[i] = fx[i] + x) of type Object(built in into java library) using which I want to call the method clone(). The above code is written in a class LoopUnroll and clone() is a method defined in the class Statement.
clone() is protected on Object for exactly this reason - that you can't just call it on arbitrary objects. It's a bit of a hack, so that all classes can inherit the implementation of the method, but don't expose that behaviour by default. (See Why is the clone method protected in java.lang.Object? for more details.)
Anyway, if you actually want instances of your Statement class to be cloneable, you should do two things:
Ensure the class implements Cloneable
Redefine the clone method as public, and just defer to the superclass implementation. (This also gives you the chance to use covariant return types to prevent callers having to cast in most cases).
The latter is what actually makes the clone method visible, and would look something the following:
#Override
public Statement clone() {
return (Statement)super.clone();
}

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