-1

I am testing the behavior of Object#clone method and I don't understand why the following code prints true, Diego, Diego, I was expecting it to print true, Diego, Armando since p.getName() == p2.getName() prints true. Could please anyone explain why p2.setName("Armando") is not modifying the p Object if they point to the same String? Thank you.

public class Main {

public static void main(String[] args) {
    Person p = new Person();
    p.setName("Diego");
    Person p2 = null;
    try {
         p2 = (Person) p.clonar();
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
    System.out.println(p.getName() == p2.getName());
    System.out.println(p.getName());
    p2.setName("Armando");
    System.out.println(p.getName());
}
}

class Person implements Cloneable {
private String name;

public Object clonar() throws CloneNotSupportedException {
    return this.clone();
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
}
Diego Ramos
  • 989
  • 4
  • 16
  • 35
  • 1
    You are setting the name of `p2`, not `p`, so the name isn't changed... – Andrew Li Feb 11 '17 at 22:59
  • But as I understand the clone method makes a shallow copy and therefore both objects point to the same String – Diego Ramos Feb 11 '17 at 23:03
  • An object is not equal to its clone, so `p2 != p`. Thus, setting `p2`'s name will not affect `p`'s name. – Andrew Li Feb 11 '17 at 23:05
  • I understand that p2 != p but then why does System.out.println(p.getName() == p2.getName()) print true ? – Diego Ramos Feb 11 '17 at 23:09
  • 2
    Because at that time both references point to the same String object. However when you call p2.setName, the name reference of p2 points then to another String object. – dunni Feb 11 '17 at 23:19
  • `==` for checking string equality is a whole different can of worms. See [here](http://stackoverflow.com/q/513832/5647260) - the strings point to same the object but the Person objects are not the same. – Andrew Li Feb 11 '17 at 23:19
  • thank you for the link Andrew, but I know how to compare Strings content, I know that you use equals to compare content but in this case I wanted to compare the references and my doubt is why 2 different objects have the same String reference i.e p.getName() == p2.getName(), thanks – Diego Ramos Feb 11 '17 at 23:22
  • Hi @dunni, could you please explain why by calling the setter it points to another String object? Thanks. – Diego Ramos Feb 11 '17 at 23:46
  • Because that's how you coded the setter (you give it the String object "Armando" when you call it, and set that object to the name variable. – dunni Feb 12 '17 at 00:01
  • @dunni and shouldn't that be set to Object p as well? Since both hold the same reference? – Diego Ramos Feb 12 '17 at 00:06
  • p and p2 are two different objects. It doesn't matter if their name variable point to the same String at the beginning. You only set the name of p2 to a different one. – dunni Feb 12 '17 at 00:19
  • @dunni I think I understand now, it is also because Strings are immutable right? If I had say an Adress object and then do Adress.street = "street" that change would be reflected in both Person objects right? – Diego Ramos Feb 12 '17 at 00:29
  • 1
    That would be so, yes. – dunni Feb 12 '17 at 00:59

1 Answers1

0

Because at that time both references point to the same String object. However when you call p2.setName, the name reference of p2 points then to another String object. Answer provided by @dunni

To reproduce the behavior I wanted I needed first to add a mutable class which works as a placeholder (Address):

public class Main {

public static void main(String[] args) {
    Person p = new Person();
    Person p2 = null;
    Address address = new Address("paseo de la reforma");
    p.setAddress(address);

    try {
         p2 = (Person) p.clonar();
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }   
    p2.getAddress().setStreet("lomas de chapultepec");
    System.out.println(p.getAddress().getStreet());
}
}

class Address {
private String street;

public Address(String street) {
    this.street = street;
}

public String getStreet() {
    return street;
}

public void setStreet(String street) {
    this.street = street;
}

  }

class Person implements Cloneable {
private String name;
private Integer edad;
private int mes;
private Address address;

public Integer getEdad() {
    return edad;
}

public void setEdad(Integer edad) {
    this.edad = edad;
}

public int getMes() {
    return mes;
}

public void setMes(int mes) {
    this.mes = mes;
}

public Object clonar() throws CloneNotSupportedException {
    return this.clone();
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Address getAddress() {
    return address;
}

public void setAddress(Address address) {
    this.address = address;
}
}

This now prints:

paseo de la reforma

lomas de chapultepec

Diego Ramos
  • 989
  • 4
  • 16
  • 35