Confusion of cloning in Java

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 created one object of this class and then cloned it. Now, when I change the value of name in one object, the value of the name remains unchanged in another. The strange thing here is in the constructor, I just use a simple link for name without creating a new String for name . Now, since String are reference types, I expected String in the clone to be changed as well. Can someone tell me what is going on? Thanks in advance!

EDIT

Code check

 CloneTest real = new CloneTest("Molly", 22); CloneTest clone = real.clone(); real.setName("Dolly"); 

I used the Inspect Variables feature in BlueJ to check the values.

+4
source share
5 answers

Suppose original is the name of the original CloneTest object, and cloned is the cloned object created with original using the clone() method.

Here's what happened:
1. Your cloned.name and original.name point to the same object, which in this case was a string.
2. Then you asked your original.name to specify another String object ("Dolly"). This happens when you assign a new String object ("Dolly") to the original.name link.
3. But cloned.name still points to the first String object ("Dolly").

Therefore, cloned.name still prints the first String object.

Now, if you can change the contents of a String object without reassigning references, the change in clone.name will be reflected in original.name . But for String objects, this is not possible due to the immutability of strings. However, you can reflect the change from clone to original with StringBuffers , which, so to speak, are mutable strings. Take a look at this sample code for it: https://gist.github.com/VijayKrishna/5967668

+4
source

Each instance of your class has different object references. You just change the link without changing the object. If you put your string in some holder object, then clone it and set the string inside the holder (not a reference to the holder, but a link to the string inside the holder), then you will have your changes in both clones.

+2
source

So you say 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 statements must pass. Your clone method has reference types in it, and upon initial cloning, they refer to the same object. But setName ("...") changes the value that the instance points to, not the value of the referenced object.

0
source

Get better clarity with @vijay's answer by looking at the 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 
0
source
 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()); } 

}

0
source

Source: https://habr.com/ru/post/1490737/


All Articles