Dubby
Dubby

Reputation: 1144

Shallow cloning in java : String and Object showing different behaviours

Questions are based on the following code :

class Car implements Cloneable
{
//Relevant constructor
     String name;
     int wheels;
     Car another;

 public Object clone()
 {
    /*DEEP
  Car n = new Car(this.name,this.wheels);
    n.another = new Car(this.another.name,this.another.wheels);
    return n;
*/ 

 return super.clone() ;
 }
}

main(String[] args) 
{
      Car c1 = new Car("merc",4);
      c1.another = new Car("baby merc",55);
      Car c2;
      c2 = (Car)c1.clone();

          //PART 1
          //HERE I TRY TO CHANGE object c2's another's name to "Han"
          System.out.println(c1.another.hashCode() == c2.another.hashCode());
/*POINT 1*/   c2.another.name  = "Han"; 
          System.out.println(c1.another.hashCode() == c2.another.hashCode());

          //PART 2
          String s = new String("gG");
          System.out.println(s.hashCode());
          s ="JAJA";
          System.out.println(s.hashCode());
}

Output :

true
true
3264
2269358
  1. I don't understand that when I change c2.another.name then c1.another.name also points to that same exact old location that the previous string "baby merc" had occupied. Shouldn't the operation at POINT1 cause a new reference location to be returned thus resulting in c2.another pointing to a new location while c1.another points to the old?
  2. And why does the same not happen when I make a string point to a new string? A new area in heap is allocated and the reference variable holds the reference of the new location. In case of c1 and c2 the reference location doesn't change even after modification! Why?

Upvotes: 0

Views: 381

Answers (3)

user3790568
user3790568

Reputation: 311

Whenever a clone() method is called on an object that contains members of any class type, then only reference variables to those members are copied.

That's why when the following statement is executed:

c2 = (Car)c1.clone();

A new object is created in the heap for c2, it contains a reference to the object another. C1 also contains reference to another. Now both c1 and c2 has reference variables that point to another. Therefore both c1 and c2 can modify the state of another.

In the case of String, a new area is allocated in the heap,

  1. whenever you use a 'new' keyword to create a String object

  2. When you create a string literal, and that string does not exist in the string pool so far.

Upvotes: 0

TheLostMind
TheLostMind

Reputation: 36304

c2 = (Car)c1.clone(); // c1.another == c2.another (yes, the references are equal, so I am using ==)

I don't understand that when I change c2.another.name then c1.another.name also points to that same exact old location that the previous string "baby merc" had occupied. Shouldn't the operation at POINT1 cause a new reference location to be returned thus resulting in c2.another pointing to a new location while c1.another points to the old?

Both c1 and c2 share the same another object / reference. They are not concerned about what changes inside it. The second line returns true because you are changing something inside another, assume that you have a box of coins and 2 people holding it. If you remove 2 coins from it, the remaining coins will be the same for both people holding it.

And why does the same not happen when I make a string point to a new string? A new area in heap is allocated and the reference variable holds the reference of the new location. In case of c1 and c2 the reference location doesn't change even after modification! Why?

You are creating 2 different objects and making the same reference point to it (one after another), so you have 2 different hash codes. This has got nothing to do with cloning.

Upvotes: 1

Henry
Henry

Reputation: 43728

c1.another is the same object as c2.another, therefore they will always have exactly the same hash code.

Moreover, the standard hash code is based on the objects identity. Changing the fields of the object does not change its hash code.

Upvotes: 1

Related Questions