0

I was working on this bug in my application and saw something very weird:

    selectedService = dataResponse.getServices().get(position);
    selectedService.setPrice(3000);
    dataResponse.getServices().get(position).getPrice(); // Returns 3000 which should be 0

Shouldn't the get method copy the object into selectedService? If not how to copy it?

2 Answers2

4

No, it shouldn't.

Java is always pass-by-value, but that value itself is a reference. So if you call a method which alters data of that particular object, it is reflected to all methods retrieving data from that particular object.

A possible solution to this problem is to make immutable types. There are classes which already implement this, for instance, all classes from the java.time package are immutable. All 'setters' of those classes return a fresh copy of the instance, with the specified value set. An example may be LocalDate::plusDays.


Here is a little example of the difference between pass-by-value and pass-by-reference.

Take a look at this code.

void main() {
    Dog myLittleDog = new Dog("Brutus");
    change(myLittleDog);
    System.out.println(myLittleDog.getName());
}

void change(Dog aDog) {
    aDog = new Dog("Jack");
}

What happens here? We pass our dog named "Brutus" to the change method. Within this method, we replace Brutus with a new Dog named "Jack". If we print the name of myLittleDog, what will be his name? Will it be "Jack"?
The answer is no. The value of the reference to the dog is copied, and is available within the change method under the name aDog. Both myLittleDog and aDog are referring to the same actual dog object in memory. But now the change method reassigns aDog with a new object. At this moment, the variables myLittleDog and aDog both refer to distinct objects. Once the change method exits, the variable aDog is unreachable and Jack is garbage collected. myLittleDog is still called "Brutus".

Conversely, this wouldn't be the case if Java was pass-by-reference. Then reassignment of aDog would also mean reassignment of myLittleDog.

See also: What's the difference between passing by reference vs. passing by value?

But then why is my selectedService still mutated?

Although values of references are copied when they are passed to methods, doesn't that mean that objects cannot change (that is, be modified). Suppose I give you a copy of my house key. You access my house and move the couch to the kitchen. Then if I enter my house, I will see that the couch has been moved. The reference value is copied, but everyone accessing the referenced object (the house), will see modifications to it.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
  • So the only way to copy the object into another and make changes to it is to make a new object with the passed values? Is there an easier way with less boiler plate? – Mohammad Hossein Kalantarian Feb 25 '20 at 14:26
  • If you want to set the price on some object, but don't want to reflect this on the other, you *must* make a copy. This is often done with the builder pattern, for example. – MC Emperor Feb 25 '20 at 14:49
0

selectedService here is a reference variable which points to whatever object you assign to it. While assigning dataResponse.getServices().get(position) to selectedService it appears as if you're assigning an object to it, however, what you're actually assigning is the reference to the original object.

As quoted on https://www.geeksforgeeks.org/clone-method-in-java-2/

Unlike C++, in Java, if we use assignment operator then it will create a copy of reference variable and not the object

To create a copy of the object

Use the clone() method to create a copy of the object as in

selectedService = (SelectedServiceClass) dataResponse.getServices().get(position).clone();
  • 'clone()' has protected access – Mohammad Hossein Kalantarian Feb 25 '20 at 14:23
  • https://stackoverflow.com/questions/16044887/clone-has-protected-access-made-public-object-clone My bad, you can use clone if you have defined your own class and overridden it with a public method, and it still is risky. I came across [this](https://stackoverflow.com/questions/869033/how-do-i-copy-an-object-in-java) which contains many methods for successful copying of an object – Kumar Harsh Feb 27 '20 at 04:25