limitless limitless - 4 months ago 8
Java Question

Why does this program output 1?

I've looked at this code and I don't understand why this program will print

1
.

First of all, in
foo(myObject)
we are assigning something to final, how is this possible?

And the second thing, after
foo()
was done, we'll get
myObject
to be null, so how can we even print it?

public class MyClass {
private int myInt;
public static void foo(MyClass myObject) {
myObject.myInt = 1;
myObject = null;
}
public static void main(String[] args) {
final MyClass myObject = new MyClass();
myObject.myInt = 2;
foo(myObject);
System.out.println(myObject.myInt);
}
}

Answer

First of all, in foo(myObject) we are assigning something to final, how is it possisble?

The object is not final, the variable in main is final. So in main, if you added myObject = somethingElse; after your initial line that sets its value, it wouldn't compile because you can't put a new value in the variable. That has no effect on whether the object the variable refers to is mutable.

And the second thing, after foo() was done, we'll get myObject to be null, so how can we even print it?

There are two separate things called myObject in your code:

  1. A variable in main

  2. A parameter in foo

Your code in foo sets the parameter to null, but that has no effect whatsoever on the variable in main. (In fact, it's impossible for foo to have any effect on the variable in main; Java is a purely pass-by-value language. All foo can do, as you've demonstrated, is modify the state of the object that both the variable and the parameter refer to, using the object reference passed into it as a parameter.)

Let's stop your code just before this line in foo:

myObject.myInt = 1;

Here's what we have in memory (leaving out some details and irrelevancies):

                        +−−−−−−−−−−−−−−−−−−−−−−+
                        | variable "myObject"  |           foo can change the
                        +−−−−−−−−−−−−−−−−−−−−−−+           *state* of this
foo can't change this−−>| Ref22458             |−−−+                   |
                        +−−−−−−−−−−−−−−−−−−−−−−+   |                   v
                                                   |    +−−−−−−−−−−−−−−−−−−−−−−−−+
                        +−−−−−−−−−−−−−−−−−−−−−−+   +−−−>| object of type MyClass |
                        | parameter "myObject" |   |    +−−−−−−−−−−−−−−−−−−−−−−−−+
                        +−−−−−−−−−−−−−−−−−−−−−−+   |    | myInt: 2               |
foo can change this−−−−>| Ref22458             |−−−+    +−−−−−−−−−−−−−−−−−−−−−−−−+
                        +−−−−−−−−−−−−−−−−−−−−−−+

...where "Ref22458" is just a name for the value of the object reference that points to the object you created in main.

Once we execute the two lines in foo:

myObject.myInt = 1;
myObject = null;

we have this in memory:

                        +−−−−−−−−−−−−−−−−−−−−−−+
                        | variable "myObject"  |           foo can change the
                        +−−−−−−−−−−−−−−−−−−−−−−+           *state* of this
foo can't change this−−>| Ref22458             |−−−+                   |
                        +−−−−−−−−−−−−−−−−−−−−−−+   |                   v
                                                   |    +−−−−−−−−−−−−−−−−−−−−−−−−+
                        +−−−−−−−−−−−−−−−−−−−−−−+   +−−−>| object of type MyClass |
                        | parameter "myObject" |   |    +−−−−−−−−−−−−−−−−−−−−−−−−+
                        +−−−−−−−−−−−−−−−−−−−−−−+   |    | myInt: 1               |
foo can change this−−−−>| null                 |−−−+    +−−−−−−−−−−−−−−−−−−−−−−−−+
                        +−−−−−−−−−−−−−−−−−−−−−−+

Note how foo could change the state of the object (myInt is now 1), and could change the value in the parameter myObject (it's now null), but couldn't change the value in the variable myObject (for two reasons: it has no access to the variable [Java is pass-by-value], and the variable is final).