So Java has references. But what about pointers and pass-by-reference? References in Java are different to PHP, C# and other languages. And this can cause some confusion.
About References in Java
In Java a reference is the value of a reference type expression.
The expression itself could, for example, be a variable or a method. Here’s an example of a reference type variable and how it is used:
BigInteger answer = BigInteger.valueOf(42); System.out.println(answer);
Here “answer” is the name of the variable. The method
valueOf returns a reference. The method
println takes a parameter of reference type. Another reference is
System is just a class name and it is used similarly to a reference in that it gives access to all static members of that class.
Other examples of reference expressions are:
"string literal" // string in string pool new Foo() // newly created object SomeEnum.ENUM_NAME // enum constant null // null literal
A reference type is anything that isn’t primitive (long, int, double, boolean etc.). So if the type of an expression is that of a class or interface, then it is a reference type. A variable of Type
Integer is of reference type. A variable of type
int is of primitive type.
Java is Pass-by-Value!
But what does it mean when a method takes a reference as a parameter. Java is “pass-by-value”. And the value of the variable “answer” is a reference. So a copy of the reference value is passed to the method. This works exactly the same as with primitive values, where a copy of the value is passed as well.
This is why in Java a method can only alter local variables, and fields of reachable objects. Usually you’d only alter fields of “this”, which is a reference and can be accessed like a local variable. You can actually alter the value of all (nonfinal) parameters, but that won’t alter the variable that was used to pass a value.
I explain pass-by-reference later.
In Java you can use
null in your code. Technically it’s not a keyword. It’s a “literal”. Just like
42 is an integer literal and
"foo" is a String literal. It is special because
null can be assigned to all variables of reference type.
From the JLS:
The null type has one value, the null reference, represented by the null literal
What you can do with References
You can do a lot and I list all operations here:
What Operations can be performed on a Reference in Java?
Method References and Lambdas
Since Java 8 you can use method references and lambdas (closures). The compiler creates an object (all objects are reference type) and so the reference isn’t different from other references. Such references can be used as alternatives to pass-by-reference (see below).
What References in Java are not
You can not see the reference. Some beginners think that toString() or hashCode() would show you the reference in HEX, but that is a misconception! Even though Java is pass-by-value, you can’t actually get that value.
You can not store a java reference into a database or file. Since it isn’t visible you wouldn’t even get the value. And during the lifetime of an object the value might actually change. That is up to the JVM.
Not an Identifier, not a Pointer, and not a Memory Address
Only the JVM knows how to interpret the reference. And when you shut down the JVM all those references are gone. That’s why you need identifier-fields if you use tools like JAX-B or Hibernate. The tool can then use those unique identifiers. The JVM probably uses 64 integers internally, but you don’t know and it doesn’t matter anyway.
Don’t confuse the variable with the reference. A reference type variable has a value and that value is a reference.
int foo has an integer as a value.
Integer foo holds a reference to an
Integer and that
Integer holds an integer value.
Java has no Pass-by-Reference!
Java simply doesn’t have that feature. And the term “reference” in “pass-by-reference” means something very different from what references are in Java! Other languages (C#, PHP, Pascal etc) have pass-by-reference and that means that not the value of a variable is passed. Instead a reference to the variable itself (not its value) is passed. Then the method (or function as they are called in other languages) can alter the value of the variable that was used when it was called. This kind of reference is just the offset to the variable, which is on another stack frame.
In other words: Java has references. Other languages have references and pointers. Java references are more like pointers than references. But they are still not the same. So you have three different things:
- Java reference: Allows access to some object or no object (null).
- Pointer: Memory address, allows access to data on heap.
- References: Allow access to variables of method invoker when passed by reference.
In the following post I explain this in more detail and list some alternatives:
Pass-By-Reference in Java