Reputation: 2037
I have this code in Java.
public class CloneTest implements Cloneable{
String name;
int marks;
public CloneTest(String s, int i) {
name = s;
marks = i;
}
public void setName(String s) {
name = s;
}
public void setMarks(int i) {
marks = i;
}
@Override
public Object clone() {
return new CloneTest(this.name, this.marks);
}
}
I have created one object of this class, and then cloned it. Now, when I change the value of name
in one object, the value of name remains unchanged in the other. The strange thing here is in the constructor, I am just using a simple reference for name
, not creating a new String
for name
. Now, since String
s are reference types, I expected the String
in the clone to be changed as well. Can anyone tell me what's going on? Thanks in advance!
EDIT
Code Testing
CloneTest real = new CloneTest("Molly", 22);
CloneTest clone = real.clone();
real.setName("Dolly");
I used the "Inspect Variables" feature of BlueJ to check the values.
Upvotes: 4
Views: 260
Reputation: 1
package com.test;
class Manager implements Cloneable
{
String firstName;
String lastName;
int age;
public Manager(String fname,String lname,int a)
{
this.firstName=fname;
this.lastName=lname;
this.age=a;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
public class TestCloning {
public static void main(String[] args) throws CloneNotSupportedException {
Manager m1=new Manager("Sadik","Tahir",26);
Manager m_clone=(Manager)m1.clone();
Manager m2=m1;
System.out.println("M1 Details:::");
System.out.println("Fisrt Name:"+m1.getFirstName()+",LastName:"+m1.getLastName()+",Age:"+m1.getAge());
System.out.println("Hashcode:"+m1.hashCode());
System.out.println("M_Clone Details:::");
System.out.println("Fisrt Name:"+m_clone.getFirstName()+",LastName:"+m_clone.getLastName()+",Age:"+m_clone.getAge());
System.out.println("Hashcode:"+m_clone.hashCode());
System.out.println("M2 Details:::");
System.out.println("Fisrt Name:"+m2.getFirstName()+",LastName:"+m2.getLastName()+",Age:"+m2.getAge());
System.out.println("Hashcode:"+m2.hashCode());
m1.setFirstName("Afreen");
m1.setLastName("Khan");
m1.setAge(25);
System.out.println("M1 Details:::");
System.out.println("Fisrt Name:"+m1.getFirstName()+",LastName:"+m1.getLastName()+",Age:"+m1.getAge());
System.out.println("Hashcode:"+m1.hashCode());
System.out.println("M_Clone Details:::");
System.out.println("Fisrt Name:"+m_clone.getFirstName()+",LastName:"+m_clone.getLastName()+",Age:"+m_clone.getAge());
System.out.println("Hashcode:"+m_clone.hashCode());
System.out.println("M2 Details:::");
System.out.println("Fisrt Name:"+m2.getFirstName()+",LastName:"+m2.getLastName()+",Age:"+m2.getAge());
System.out.println("Hashcode:"+m2.hashCode());
}
}
Upvotes: 0
Reputation: 2694
Assume that original
is the name of original CloneTest object, and cloned
is the cloned object that you created from original
using the clone()
method.
This is what happened:
1. Your cloned.name
and original.name
are pointing at the same object, which in this case was a String.
2. Then you asked your original.name
to point to a different String object ("Dolly"). This happens when you assign the new String object ("Dolly") to the reference original.name
.
3. But, the cloned.name
still points to the first String object ("Dolly").
Hence, cloned.name
still prints the 1st String object.
Now, if you are able to change the content of the String object without reassigning the references, then the change in clone.name
will reflect in original.name
. But for String objects, this is not possible due to the immutability of Strings. However, you can reflect the change from the clone
to original
with StringBuffers which are mutable strings so to speak. Take a look at this example code for the same: https://gist.github.com/VijayKrishna/5967668
Upvotes: 4
Reputation: 11298
Get some better clarity along with @vijay answer by looking hash code.
CloneTest real = new CloneTest("Molly", 22);
CloneTest clone = (CloneTest) real.clone();
int h1=real.name.hashCode();
int h2=clone.name.hashCode();
System.out.println("h1 " + h1 + " h2 " + h2); // same
real.setName("sak");
h1=real.name.hashCode();
h2=clone.name.hashCode();
System.out.println("h1 " + h1 + " h2 " + h2); //different
Output :
h1 74525175 h2 74525175
h1 113629 h2 74525175
Upvotes: 0
Reputation: 174
So are you saying you are doing something like:
public void testSomeMethod() {
CloneTest a = new CloneTest("a", 1);
CloneTest b = (CloneTest) a.clone();
a.setName("b");
assertFalse(b.name.equals(a.name));
assertEquals("b", a.name);
assertEquals("a", b.name);
}
?
If so, then all these assertions should pass. Your clone method has reference types in it, and when initially cloned, they refer to the same object. But the setName("...") changes the value that instance points to, not the value of the referred to object.
Upvotes: 0
Reputation: 2006
Each instance of your class has different references to an object. You you're just changing reference not modifying object. If you place your string in some holder object, then clone it and set string inside the holder (not a holder reference but string reference inside holder) then you'll have your changes in both of clones
Upvotes: 2