Understanding deepCopy concept - java

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

Related

What is the advantage of creating object with clone() over constructor?

Whenever I'm doing shallow cloning then if my class consists of any user-defined reference type then there reference value will copied but not values, but if I'm writing String s="something", then even though s is an object but it is directly copied into the cloned object, why so? Does it mean pre-defined object will be copied but user-defined object reference will be copied?
If you want an object of the same state, then you can use clone(). If there's no difference between the two I would say use a constructor. Cloning requires an object to already have been made in order to make another instance, not to mention the implementation of Cloneable is already fairly messy.
Also note, the object you attempt to use clone() on must actually implement Cloneable and override the method in order to actually work.
It is not that "predefined" object types are deep copied and "user defined" object types are shallow copied.
Your cited example is this :
String s = "something";
Yes, a string literal is an "object" but strings are immutable objects, and more importantly they are special down to the level that they are built into the design of the language itself. REALLY what you are doing here is nothing different from saying YourClass varName = new YourClass(); Here, you create a new String object with value "something" (if the literal does not exist in the string constant pool) and store a reference to that object to your variable s of type String.
You can shallow copy a string just like you can shallow copy a user defined object:
String s = "something"; //in this example this would be the same as saying new String("something")
String imAShallowCopyOfS = s;
System.out.println(imAShallowCopyOfS == s); //true
You are still just copying the reference that s points to into imAShallowCopyOfS. I would suggest you shy away from using Strings to learn the behavior of references in java, though, as they are rather special objects that receive some special treatment by the compiler/vm.

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.

modify value in variable

I have a problem with one class in java
this class is public and extends of DefaultHandler
all method of this class are public too ... but the variables are private...
My problem is that if I copy the value in other variable and modify this second variable the first change too.
is like static variables.. but they are no static... any idea!!!
thanks in advance
This is because you are actually modifying the same object. For instance, if you have
Object obj = new Object();
Object obj2 = obj;
You don't actually copy anything, you simply make obj2 "point" (not quite the right term, but it will work for now) to obj. Any changes to obj2 will be reflected in obj. Therefore, if you want to actually copy it, you need to physically create a new Object and then manually copy all of the values into the new creation. You could implement the prototype pattern to copy the object. Primitives don't behave this way so if you were to do the same thing with a double or an int for instance, it would behave the way you expect.
Does all of that make sense?
You are probably having a problem with passing by reference versus passing by value. This page explains what I mean http://www.cs.umd.edu/class/sum2004/cmsc420/sum4v3e01/node6.html.
You probably are copying a reference to a changeable object, not the object itself; so after the copy, you have two references to the same object. Changing that object through either reference will have the same effect.
I can't tell you how to copy the actual object because there's no generic way to do it, but many classes provide a copy constructor or some other way to duplicate themselves. If you need help with that you'd have to provide more details.

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

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).

Categories