Table of Contents
- Table of Contents
- Introduction
- Changes by the Method Invoked
- Reassignment Within the Method
- The Impact of Final
- Summary
Introduction
When you invoke a Java method and pass in an object as a parameter, what is handed to the method is a copy of the reference to that object (AKA the object’s address). The reference however, points to the same object somewhere else in memory as is used by the calling code.
Changes by the Method Invoked
Because both the calling code and the method invoked both reference the same object elsewhere in memory, any changes made within that object (such as calling setters or other state altering methods, like clear(), etc.) will impact not only the object within the scope of the current method, but also that same object when referenced again back in the calling code.
public static void demonstrateModifications(@NonNull List<String> myList) {
myList.clear();
}
@Nested
class DemonstrateModificationsTest {
...
@Test
void demonstrateModifications_whenInvoked_changesObject() {
// Setup
List<String> myList = new ArrayList<>();
myList.add("ABC");
// Execution
PassByReferenceDemo.demonstrateModifications(myList);
// Validation
assertEquals(0, myList.size());
}
}
Reassignment Within the Method
Since the method received a copy of the object’s reference (think of it like an address), we can change what object in memory we use within the method and not impact the calling code, as this reassignment only impacts the copy of the address we have within the method.
If you and your friend Ann both write down where your third friend, Suzy, lives, but then you discover a typo and fix it on your paper. Ann will still have issues sending mail to Suzy unless you also tell Ann about the typo. Each paper is an independent copy of the address. Here, the copy of the address for the calling code and the method invoked with that object as a parameter are independent copies. They are separate copies, but they both take you to the same address (object).
public static void demonstrateReassignment(@NonNull List<String> myList) {
myList = new ArrayList<>();
}
@Nested
class DemonstrateReassignmentTest {
...
@Test
void demonstrateReassignment_whenInvoked_changesObject() {
// Setup
List<String> myList = new ArrayList<>();
myList.add("ABC");
// Execution
PassByReferenceDemo.demonstrateReassignment(myList);
// Validation
assertEquals(1, myList.size());
assertEquals("ABC", myList.get(0));
}
}
The Impact of Final
The final keyword on an input parameter only prevents reassigning the reference to a new address (a different object in memory) within the method. It doesn’t prevent calling methods on that object that change the state of that shared object in both the method and the calling code. Just like in the pass-by-value scenario, the final keyword on an input parameter can help the method avoid copy
The final keyword on an input parameter tells the compiler to enforce that we do not assign that input parameter a new value within that method. This can help with things like copy/paste errors or issues with instance fields sharing a the same name as input parameters and assigning a value to the wrong one.
public static void demonstrateFinal(final @NonNull List<String> myList) {
myList.clear();
// myList = new ArrayList<>();
}
@Nested
class DemonstrateFinalTest {
...
@Test
void demonstrateFinal_whenInvoked_changesObject() {
// Setup
List<String> myList = new ArrayList<>();
myList.add("ABC");
// Execution
PassByReferenceDemo.demonstrateFinal(myList);
// Validation
assertEquals(0, myList.size());
}
}
If you were to uncomment the line in the code above that does the reassignment, then it would not compile due to the presence of the final keyword.
Summary
When a Java method is invoked with an object as an input parameter, it receives a copy of the address/reference to the object. However, both the calling code and the method still point to the same object elsewhere in memory. The final keyword prevents reassigning the input parameter variable name to a new object reference, but it does not prevent state modifications for the shared object.

Leave a comment