What is this field-by-field copy done by Object.clone()? - java

In Effective Java, the author states that:
If a class implements Cloneable,
Object's clone method returns a
field-by-field copy of the object;
otherwise it throws
CloneNotSupportedException.
What I'd like to know is what he means with field-by-field copy. Does it mean that if the class has X bytes in memory, it will just copy that piece of memory? If yes, then can I assume all value types of the original class will be copied to the new object?
class Point implements Cloneable{
private int x;
private int y;
#Override
public Point clone() {
return (Point)super.clone();
}
}
If what Object.clone() does is a field by field copy of the Point class, I'd say that I wouldn't need to explicitly copy fields x and y, being that the code shown above will be more than enough to make a clone of the Point class. That is, the following bit of code is redundant:
#Override
public Point clone() {
Point newObj = (Point)super.clone();
newObj.x = this.x; //redundant
newObj.y = this.y; //redundant
}
Am I right?
I know references of the cloned object will point automatically to where the original object's references pointed to, I'm just not sure what happens specifically with value types. If anyone could state clearly what Object.clone()'s algorithm specification is (in easy language) that'd be great.

Yes, a field by field copy does mean that when it creates the new (cloned) object, the JVM will copy the value of every field from the original object into the cloned object. Unfortunately this does mean that you have a shallow copy. If you desire a deep copy, you can override the clone method.
class Line implements Cloneable {
private Point start;
private Point end;
public Line() {
//Careful: This will not happen for the cloned object
SomeGlobalRegistry.register(this);
}
#Override
public Line clone() {
//calling super.clone is going to create a shallow copy.
//If we want a deep copy, we must clone or instantiate
//the fields ourselves
Line line = (Line)super.clone();
//assuming Point is cloneable. Otherwise we will
//have to instantiate and populate it's fields manually
line.start = this.start.clone();
line.end = this.end.clone;
return line;
}
}
Also one more important thing about the cloning is, the constructor of the cloned object is never invoked (only the fields are copied). So if the constructor initializes an external object, or registers this object with some registry, then that will not happen for the cloned object.
I personally prefer to not use Java's cloning. Instead I usually create my own "duplication" methods.

It means a shallow copy -- the fields are copied, but if you have any references, what these point to is not copied -- you will have two references to the same object, one in the old object and one in the new, cloned object. However, for fields that have primitive types, the field is the data itself, so they get copied regardless.

newObj.x = this.x; //redundant
newObj.y = this.y; //redundant
that's right - these are redundant, since they will have already been copied by Object's clone() method.
Thinking of it as a data copy is correct. Primitive types are copied, and references are also copied so they point to the same object. For example,
class A implements Cloneable {
Object someObject;
}
A a = new A();
a.someObject = new Object();
A cloneA = (A)a.clone();
assert a.someObject==cloneA.someObject;

The default clone performs shallow copy of values. For primitive values, this is enough and no extra work is needed.
For objects, the shallow copy means copying the reference only. Therefore, in these cases a deep copy is usually needed. The exception for this is when the reference points to an immutable object. Immutable objects can't have their apparent state changed, therefore their references can be copied around safely. For example, this applies to String, Integer, Float, enumerations (if not made mutable by mistake).

Related

How does java clone() really use shallow copy?

I know It might be already asked, but my question is something different. I've searched and I know java method object.clone() uses shallow copy which means copying references and not the actual objects. Let's say I have a dog Class
Class Dog{
public Dog(String name, DogTail tail, DogEar ear){
this.name = name;
this.tail = tail;
this.ear = ear;
}
}
DogTail t = new DogTail();
DogEar ear = new DogEar();
Dog dog1 = new Dog("good", t,ear);
let's say I want to get a copy of dog1.
Dog dognew = dog1.clone();
If this clone() method uses shallow copy, it means copying references. So If I change t object created above or ear method, it's gonna change in the dognew object or vice versa. How is this cloning good? This question was born because someone said that creating an big huge object is worse than cloning, as you save performance while using clone() method.
The default version of clone() method creates the shallow copy of an object.
The shallow copy of an object will have exact copy of all the fields of original object. If original object has any references to other objects as fields, then only references of those objects are copied into clone object, copy of those objects are not created. That means any changes made to those objects through clone object will be reflected in original object or vice-versa.
To create a deep copy of an object, you could override the clone() method.
protected Object clone() throws CloneNotSupportedException
{
DogTail tail = (DogTail) this.tail.clone();
Dog dog = (Dog) super.clone();
dog.tail = tail;
return dog;
}
"So If I change t object created above or ear method, it's gonna change in the dognew object or vice versa."
It depends on what you mean by "change":
If you mean change the state of the DogTail instance that t references, e.g. t.setSomething(someValue);, then yes. It's the same instance, doesn't matter who causes a change or where the change happens.
If however you mean change what t in the clone references, e.g. t = new DogTail();, t in the original will not be affected. The t in the clone and the original will reference different instances after that.

Understanding deepCopy concept

I'm reading about the so called UserType in Hiberante that declares the deepCopy(Object) method. Authors suggest we use the following implementation for immutable classes:
Because MonetaryAmount is an immutable class, the deepCopy() method
returns its argument.
Why? I thought the deepCopy implementing as follows:
public Object deepCopy(Object value) throws HibernateException {
return value;
}
is actually a shallow-copy. What did I miss?
Immutable object's cannot change it's state. So it doesn't matter if you return the same object. Since no modification can be done to it anyway. So it actually acts like a deepCopy when there is no copy at all.
Let's take an example of String.
String s1 = "hello";
String s2 = new String(s1);
String s3 = s1;
It doesn't matter what operation you perform on any of the variables, it's not going to affect the other 2.
If you return the same object you put into a method, then that's not any copy at all, neither swallow nor deep. A shallow copy would be if you copied all the references in the given object to a new one. A deep copy is when you dereference everything and create copies of all the child, etc. objects of your original.
Example:
MyObject has a reference to a Calendar object.
Shallow Copy to "MyCopy":
MyCopy (a new object, not the same (==) as MyObject) gets a reference to the same Calendar object.
Problem: If I now modify the Calendar of "MyCopy", the Calendar of "MyObject" will change, too, because it is the same one.
Deep Copy:
MyCopy gets a new Calendar which is a complete (itself deep) copy of the MyObject Calendar.
Advantage: If I now modify the Calendar of MyCopy, nothing changes for the one of MyObject.
If you have an immutable object, there is no need to deep copy it, because you can simply use the same object everywhere - it cannot be modified (thus immutable), so that is perfectly safe - and fast.
see also Wikipedia

Getting a copy of an object

I don't fully understand when Java passes a copy/value and when it passes a "reference" (the pointer).
I'm trying to assign a copy of a static object I have, but I'm not sure how to go about it.
I have this:
static ArrayList<MyObject> myObjects;
I want to get a copy of myObjects so that I can play around with the values without affecting the original. Does it pass a reference or a copy/value when I use a getter like so:
public static ArrayList<MyObject> getMyObject()
{
return ThisClass.myObjects;
}
What does that return? If it's a reference, how can I get a copy?
I've seen these:
(How do I copy an object in Java?)
(Java: getter method vs. public instance variable: performance and memory)
(Is Java "pass-by-reference" or "pass-by-value"?)
(How can Java assignment be made to point to an object instead of making a copy?)
But I still don't quite understand what I'll get back.
Java will always return a reference and not a copy as long as it's not a primitive type (aka long,int,short,etc or one of the primitive wrappers Long,Integer, Short.
To get a copy you will need to either copy the data, use a copy constructor, or use the method clone which will create a new object with the appropriate values.
Example of a copy constructor with a list, by default this is a "shallow copy" meaning the objects inside are the same.
List<MyObject> myNewCopiedList = new ArrayList<MyObject>(oldList);
For a "deep copy", meaning the objects inside can be mutated without affecting the originals you will need to make a new List then add copies/clones of the object and add.
Example, assuming MyObject has a copy constructor or a clone method.
List<MyObject> myNewCopiedList = new ArrayList<MyObject>();
for (MyObject myo : oldList){
myNewCopiedList.add(new MyObject(myo)); // if there is a copy constructor
myNewCopiedList.add(myo.clone()); // if there is clone method
}
Think of it this way. Java is always pass by value.
For primitives, it is pass by value(actual value).
For objects, it is pass by value-of-reference.
public int square(int a) { //The parameter a is copy of actual int itself.
//So now there are 2 ints
a=a*a; //Only local copy a is actually modified.
//The integer variable passed(in caller function) is not modified.
return a;
}
If you call doSomething(d) where d is an object, a copy of reference pointing to this object is assigned to parameter a but there is only one object.
public void doSomething(Object a) {
// Here the parameter is a reference which points to an
// object, not the object itself
a.doMore(); //But doMore() does things using a different ref but on the same object.
//The object can be modified!
Object b = new Object();
a = b; //Object referenced by passed parameter does not change but
//copy of reference now points to different object.
// Now there is no reference of original object passed in this method.
}
Technically, Java is always pass-by-value. However, for a beginner's thinking, it's easier to think about it this way:
If it's a primitive type, it's pass-by-value.
If it's an object, it's pass-by-reference.
So in your example, you are returning a reference to the same static object in ThisClass. The reason I say this is technically pass-by-value is because your variable myObjects actually stores the memory address of the ArrayList<MyObject> which you declared, and it's this which is passed.
In order to properly make a copy of an object, one must know which non-primitive fields encapsulate
Mutable aspects of the object's state, but not its identity
The identity of an object and other immutable aspects, but no mutable aspects.
Aspects of the object which are expected never to be exposed to any code which might mutate them (and not identity)
Mutable aspects of the object's state, as well as its identity
Based upon what a field encapsulates, a correct copy of Foo
If one of Foo's field which encapsulates mutable state, a the corresponding field in a copy of Foo should hold a reference to a different object with the same state.
If a field encapsulates object identity, that field in the copy must hold a reference to the same object as in Foo--not a copy.
If a field encapsulates only immutable aspects other than identity, then a copy of Foo may either hold a reference to the same object as in Foo, or any object which has the same immutable state, as convenient.
If a field encapsulates both mutable state and identity, because the first two requirements will conflict, it will not be possible to copy the object in isolation.
In some cases, it may be possible to copy a set of mutable objects which use references to each other to encapsulate both state and identity. Such a copy must be performed on the set as a whole; for each object within the set, any field which in the original object encapsulates both the mutable state and identity of another object in the original set must in the copy refer to the corresponding object in the copied set.

Java objects confusion

I am currently creating an Android app and thought that I had a problem with saving data internally, etc. It turned out that the problem had nothing to do with that, but with my understanding of Java.
The problem is that when I do
myObject1 = myObject2;
and use myObject1 in myObject3 which might be a list, or whatever (in my case a Hashtable) and then change myObject2, myObject3 gets changed accordingly, as well. What is this called, and where can I learn more about it? How do I assign myObject2 to myObject1 so that myObject1 is completely "independent"?
Variables that are Objects in Java are called references and refer to the same location in memory. If you want two objects of the same type that don't refer to the same location in memory in need to allocate memory for them on your machine by using the new keyword.
Below both variables myObject1 and myObject2 are references to an OBJECT1 object, but that don't exist at the same memory location:
OBJECT1 myObject1 = new OBJECT1();
OBJECT1 myObject2 = new OBJECT1();
If assigning an object to another is important you can look into the clone() method or use a copy constructor:
public OBJECT1(OBJECT1 toCopy)
{
this.field1 = toCopy.field1;
this.field2 = toCopy.field2;
this.field3 = toCopy.field3;
this.field4 = toCopy.field4;
}
Those variables are references to an object; think of each variable as the end of a string. The other end is tied to an object. If you assign a variable, you're tieing a new string onto an object.
To create a copy, you (unsurprisingly) need to create a copy. Sometimes, this is easy: there might be a copy constructor that lets you do this:
ArrayList<String> copy = new ArrayList<String>(oldArrayList);
Other times, you may be a method that makes a copy; for example, some classes implement the clone() method:
Foo copy = (Foo) otherFoo.clone();
You just have to study the API of a class to find a way to copy an object.
That depends on what myObject is. The word you are looking for is clone if you want to have an exact copy. But not all Objects support clone, so you may have to build your own clone method that (as #Hunter) pointed out needs to allocate new memory through the new keyword.
So in Java or in any OOP language
if you consider the statement
Object obj = new Object()
obj is called the handle which actually points to the location where the actual Object is stored.
so when you do obj1 = obj you are getting 2 handles which are actually pointing to the same location
so if you do obj1.setSomething() it will be reflected on the obj.getSomething() call also.
Variables contain references to objects. In other languages, references are often called pointers. So doing myObject1 = myObject2; makes the myObject1 variable reference the same object as the myObject2 variable.
If you want to make a copy of an object, the best way is to implement it yourself, for example using a copy constructor:
public MyClass(MyClass other) {
this.foo = other.foo;
this.bar = other.bar;
...
}
and thus do
myObject1 = new MyClass(myObject2);
When you assign an object o1 to another object o2 you make the o2 pointing to o1. So whenever you change object o1 object o2 changes accordingly.
It happens the same with objects inside a list. This is because in Java when you assing an object to another you don't copy the content but it is like you "share" it.
The only way to create another object indipendent from everything is using new and then copy each attribute.

Why isn't there a easy way to copy objects in Java?

I have a class TimeLine in my GUI. I have a function where I would like to copy this TimeLine and modify the data in it whithout the TImeLine in my GUI won't be affected.
I've searched some forums and haven't found an easy way because Java let's the references stick. Why isn't there a easy way to create a new Object (TimeLine) that hasn't the reference to the previous one?
Please help my make a copy of this TimeLine object!
The clone() method and Cloneable interface, suggested by other authors here, were created with the incorrect assumption that it would be a good idea to have a generic copying method. The default implementations does a shallow clone of the current object, but you could override it to do a deep clone.
There is no correct, generic way to copy arbitrary objects, what you want to copy depends on the objects involved. For example, immutable objects never need copying (that'd just be a waste of space), while some types of objects can't be copied (how would you copy a FileOutputStream, for example?).
The way I find most elegant is immutable objects with methods that return a copy with just one field changed:
class Pony {
private final String name;
private final Color color;
private final int tailLength;
// constructors and accessors omitted
Pony withName(String newName) {
return new Pony(newName, color, tailLength);
}
Pony withColor(Color newColor) {
return new Pony(name, newColor, tailLength);
}
Pony withTailLength(String newTailLength) {
return new Pony(name, color, newTailLength);
}
}
// Usage:
Pony tony = new Pony("Tony", Color.DAPPLE, 32);
Pony maurice = tony.withName("Maurice") // Maurice is like Tony, but black.
.withColor(Color.BLACK);
Unfortunately, you get a lot of boilerplate this way, and there's no mainstream IDE support either (there may be plugins, though). Related to this is the Builder pattern recommended by Josh Bloch in Effective Java.
Instead of clone() you might want to consider writing a copy constructor for your class:
public TimeLine(TimeLine original) {
this.foo = original.foo;
this.bar = original.bar;
}
Be careful when copying the value of any reference fields in your class. Be sure whether you want a shallow copy or a deep copy.
In Java using the operator "=" your are simply copying references to objects. If you want to implement copy by value use clone operation (clone() method of the class Object) or implement your own clone method (overriding the implemented one).
Pay attention that if your class stores other object inside it, these objects should eventually be cloned too (DEEP COPY).
if you want to copy an object use clone()
if I misunderstood your question please comment
You're looking for the clone method. (I've gone back and forth as to which documentation to cite, that is Wikipedia, it's treatment is more thorough. The Java doc's are more official, of course).
Eg.
MyObject a = new MyObject();
a.setSomething( 2 );
MyObject b = a.clone();
// now b.getSomething().equals(a.getSomething()) (maybe == too, depends on class)
// and b.equals(a)
// b != a

Categories