Firstly, I would point out the difference between the two examples you've shown. The method Change#change(Student)
public class Change {
public void change(Student s) {
s.name = "Fred";
}
}
Compared to Change#dontChange(int)
public class Change {
public void dontChange(int i) {
i = 42;
}
}
The most notable difference between these two methods is where they assign (=) the value they're passing. s.name
vs i
. Note the presence of the dot operator (.)
indicating that there's access of an Object
's field or method. This can help start the explanation of why change(Student)
updates the value it assigns to as compared to dontChange(int)
.
There was reference of looking into the difference between pass-by-value
and pass-by-reference
in other answers, and that will be required information for WHY this happens. However, I think there should be a slightly deeper understanding of what a variable is in java for that to help explain it. The easiest explanation I find is that a variable in java is a number. Period. Always. Now that might seem weird, right? You obviously have an object when you do Student stu = new Student()
, but that's only partially correct. You do instantiate (create/construct) an object, but the value stored in Student stu
can actually be thought of as a number pointing to a spot in memory where stu
's values are stored. There IS a difference in how these number are handled, but they are, in essence, all numbers.
Knowing this, you can work with the thought that values passed to a method in java are always passed-by-value
. If you wanted to test this you could see the output of changing the body of Change#change(Student)
to
public class Change {
void change(Student s) {
Student newStudent = new Student();
newStudent.name = "Fred";
s = newStudent;
}
}
You may expect the output name to still be "Fred"
, but it should result in "Jane"
. We didn't modify the object that Student s
refers to, we updated what the variable s
points to. The difference being that in the original Change#change(Student)
method you assigned the value "Fred"
to the name
field (s.name
) of the object that Student s
refers to.
When you call Change#change(Student)
with the variable stu
the parameter s
's value becomes the same identifying number that stu
points to, but the variables themselves are entirely different. They only, when s
is initialized, have the same value (a number pointing to a space in memory).
It should be noted that assigning "Jane"
and "Fred"
to the Student
's name
field is actually assigning a reference to a String
which represents "Jane"
or "Fred"
to the Student
's name
field. As the name
field's type is, assumed to be, String
which is not a primitive type. Meaning it's a reference to some String object in memory.