I have the following code which has
a mutable Person class, String and a method to modify the instances of String and Person
class Person{
int a = 8;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
@Override
public String toString() {
return "Person [a=" + a + "]";
}
}
--
public class TestMutable {
public static void main(String[] args)
{
Person p = new Person();
p.setA(34);
String s = "bar";
modifyObject(s, p); //Call to modify objects
System.out.println(s);
System.out.println(p);
}
private static void modifyObject(String str, Person p)
{
str = "foo";
p.setA(45);
}
}
The output is as expected. It prints
bar
Person [a=45]
Now, my question is
What is happening at the place you say str="foo" ?
Initially let's assume that s='bar' and the data resides in 0x100 memory
Now the reference of string is passed to another method, the other method tries to change the contents of the memory location(0x100) to 'foo' using s="foo". Is this what is happening, or is 'foo' is created in differennt memory location ?
Does java pass references by value ?
In this function call "modifyObject(s, p);" you are sending the value of variable s to modifyObject method's local variable str. So a new variable is created and its value is changed but the original one remains unchanged.
Java always passes arguments by value NOT by reference.
Let me explain this through an example:
I will explain this in steps:
1- Declaring a reference named
f
of typeFoo
and assign it to a new object of typeFoo
with an attribute"f"
.2- From the method side, a reference of type
Foo
with a namea
is declared and it's initially assigned tonull
.3- As you call the method
changeReference
, the referencea
will be assigned to the object which is passed as an argument.4- Declaring a reference named
b
of typeFoo
and assign it to a new object of typeFoo
with an attribute"b"
.5-
a = b
is re-assigning the referencea
NOTf
to the object whose its attribute is"b"
.6- As you call
modifyReference(Foo c)
method, a referencec
is created and assigned to the object with attribute"f"
.7-
c.setAttribute("c");
will change the attribute of the object that referencec
points to it, and it's same object that referencef
points to it.I hope you understand now how passing objects as arguments works in Java :)
In
modifyObject
, When you assign tostr
, you're not mutatingstr
, you're setting it so that it points to a different object. Since it's passed by value, thestr
pointer local to yourmodifyObject
method is a copy of thes
pointer inmain
, so when you change the former, it does not affect le later.On the other hand, when it comes to
p
, the one inmodifyObject
is still a copy of the one inmain
, but both pointers refer to the very same object in memory, hence if you call a method on it frommodifyObject
, you're actually mutating the thing pointed to byp
.Sometimes people get confused when passing by reference. It's possible to change the object that the reference refers to (giving the impression of pass-by-reference), but it is not possible to modify reference itself. So it still remains pass-by-value.