Java Reference
In-Depth Information
When you pass a primitive to a method, the JVM preserves the original value and makes a new
primitive (literally, a copy) with the same value for use in the method. The JVM consequently has two
values, the original
primitiveInt
field in
PassByTest
and the
primitiveInt
argument to the
passBy
method. Therein lies the heart of the issue: Because the JVM makes a new primitive, the original never
gets modified.
Even if the
passBy
method returned the primitive value, it would not change the original value. Until
we re-assign the original value, it remains whatever it was originally set to (0 in this case). If we assign the
return value of the method to the original primitive, that works. Again, though, we have two different
values, and we assign the value of the new one (created by the method) to the old one. Consider the
modified
PassByTest
class in Listing 6-17.
Listing 6-17. PassByTest with a return value for the passBy method
package com.apress.java7forabsolutebeginners .examples.hello;
public class Hello {
static int primitiveInt = 0;
static IntegerWrapper intWrapper = new IntegerWrapper();
public static void main(String[] args) throws Exception {
passBy(primitiveInt, intWrapper);
System.out.println("primitiveInt = " + primitiveInt +
"; intWrapper.objectInt = " + intWrapper.objectInt);
}
public static int passBy(int primitiveInt, IntegerWrapper intWrapper) {
primitiveInt++;
intWrapper.objectInt++;
return primitiveInt;
}
}
The
passBy
method now returns an
int
, but the output remains the same (
primitiveInt
remains 0).
I know I've hammered the point repeatedly, but, again,
primitiveInt
in the method is a different
primitive than the
primitiveInt
field in the class. Remember, the compiler makes a copy of it when it
calls the method.
Now, let's look at what happens to
IntegerWrapper.objectInt
. Because
IntegerWrapper
is an object,
the value that gets passed is its address in memory (that is, a pointer to the object). There's only one
IntegerWrapper
object, named
intWrapper
, in memory (because we used the
new
keyword with that class
only once). So, any work done on
intWrapper
is done to the same object. Consequently, when we
increment
intWrapper.objectInt
, the change makes it back to the
main
method, because the
main
method still looks at the same spot in memory. That is,
intWrapper
continues to be at the same location
in memory, and so we change that object where we could not change a primitive.
If all that seems confusing, you're in good company. It stumped me enough that I remember clearly,
thirty years later, when I first realized that something (a function in Fortran, in fact) was working on the
pass-by-reference model. It's a tricky concept, but you have to master it to be able to program in Java
(and many other languages).
Java has a particular reason for passing objects by reference, by the way. Suppose you have a
complex object. Such a class might have several fields, and many of those fields might themselves be
references to other objects (remember the composition technique), and so on, to any depth you can
imagine (object stacks, as such things are called, are often many layers deep). What exactly is the value of