Java objects confusion - java

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.

Related

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

Creating an Object inside a loop

Is it a good practice to create an Object inside a loop. I am pointing towards the following code:
for(some condition){
SomeClass a = new SomeClass ();
System.out.println(a);
}
So this would create a new instance of SomeClass for each iteration. So number of instances will be equal to number of iterations. And then these will later be collected by GC.
Is it better to reuse a SomeClass object inside the loop. Something like this:
SomeClass a = null;
for(some condition) {
a = new SomeClass();
System.out.println(a);
}
As far as I understand this, the second way is better as this will just create the SomeClass object once and will reuse it in every iteration. But I am doubtful. Please confirm this, or let me know where my fundamentals are incorrect.
The difference is that in your second case, your a variable will still be in scope when the loop is over
other than that, they're essentially the same, even from a garbage collection point of view.
Strings are reference types(albeit immutable ones), and it doesn't really matter whether you declare a new variable for them or just overwrite the same variable each time. You're still creating a brand new string every time.
Be careful not confuse the 'Object' itself and a 'Reference' to an 'Object':
For instance the following code creates a (null) Reference, but no object is created.
Object a = null;
The following code create boths an Object AND a reference to that object (the reference is held in a variable called 'a'):
Object a = new Object();
The following code creates new Object and 'repoints' an existing (reference) variable to point to the new Object: if the variable 'a' already held another reference, 'a' forgots it. [but that doesn't mean other variables may still point to the old object referenced by 'a'].
a = new Object(); // it is the reference 'a' that is 're-used' here not the object...
Everytime you re-run the that statement above in your loop; you are indeed creating a new object ; and you are 're-pointing' 'a' to that new object.
The previous reference (i.e. reference held in 'a') will be forgotten each time; and (assuming we have a single-threaded program here) that means the object it pointed to will have zero references pointing at it now: which means the object is eligible for Garbage Collection. Whether this Garbage collection happens or not at this point in time - I don't know I'm afraid.
But I would say : that there is no difference in your coding examples in terms of when Garbage Collection happens; whether or not the 'pointer-type' is already defined as an 'Object' outside of the loop, or repeatedly redefined within the loop.
The following (useless) examples might help illustrate the difference between the 'Create-an-Object' and 'Point-a-Reference' actions that the code does in one go:
// This creates an object ; but we don't hold a reference to it.
public class TestClass {
public static void main(String[] args) {
for (int n=0;n<100;n++) {
new Object();
}
}
}
And to contrast:
// This creates a reference ; but no object is created
// This is identical to setting the reference to 'null'.
public class TestClass {
public static void main(String[] args) {
for (int n=0;n<100;n++) {
Object o;
}
}
}
Both create an equivalent amount of strings because String is immutable. Anytime a String is assigned a new value, a new String is created.
Let's assume you meant to use a mutable object in your example.
Option 1
for(some condition)
{
Object o = new Object();
System.out.println(o);
}
This will create a new Object o for each iteration of the loop.
Option 2
Object o;
for(some condition)
{
o = new Object();
System.out.println(o);
}
This will create a new Object o for each iteration of the loop.
Even for a mutable object, you get the same result either way!
the 2nd is not "better".
String a="foo"; reuse a literal string from string pool. That is, no matter you declare the a in/outside the loop, there is no difference in terms of memory. But they have different scope. I think it is another issue.
even if with your edited version, with general SomeClass, it is not like what you thought:
the second way is better as this will just create the SomeClass object once and will reuse it in every iteration .
It creates new object in each loop step. a is just a reference to the object. The point is, if the object(s) you created referenced by other objects, GC will not collect it, and release the memory. For example, the old (<=java1.6) String.subString() method, it holds the original String as char[], so GC won't clean the original String.
You are confusing the variable you assign an object to, to the actual object instance.
Both code samples create the equivalent amount of objects. The second one will keep one instance in larger scope, thus it will be available for a longer time.
according to my knowledge - in bigger application (not in this) but in bigger is better to use static block for object creation - because static block code is executed only once when class is loaded into memory. Technically, you can can have multiple static blocks in a class, although it doesn’t make much sense
remember: Static block can access only static variables and methods
The only difference is that in the second case, variable will still be in scope when the loop is over ,no. of objects that are created in both the cases are equal as Strings are immutable
as you have just edit the question still in this case new Objects are created in the memory at each iteration in both the cases
Since the topic has changed quite a bit. I update:
If you really want to reuse the once create object you will have to write that code yourself. It could follow this principle:
SomeClass a = new SomeClass();
for(some condition) {
a.reset();
//do something with a
}
Where the SomeClass.reset() method handles all the details (which are dependant on your actual usage of the object).
it is all about scope,
if you do your second way:
SomeType someFunction(){
...
SomeClass a = null;
for(some condition) {
a = new SomeClass();
System.out.println(a);
}
...
return something
}
object a will exist in memory till end of someFunction while for first method, its lifecycle is within single iteration of loop

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.

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