Explain Codes LogoExplain Codes Logo

Can I pass parameters by reference in Java?

java
pass-by-reference
mutable-wrappers
atomic-references
Anton ShumikhinbyAnton Shumikhin·Jan 31, 2025
TLDR

In Java, parameters are always passed by value. Yes, you heard that right. Whether it is a primitive type or an object reference, Java treats them all the same - like Pf Chang's Take out, they all get packed the same way! Each parameter receives a copy, either of the primitive value or the reference to the object. Rebonding a new object to a parameter reference won't reassign the original object's reference outside the method.

Let's illustrate:

class Counter { public int count; } public static void incrementCounter(Counter ctr) { ctr.count += 1; // Ding! Counter goes up. Now serving number 1. } public static void main(String[] args) { Counter myCounter = new Counter(); incrementCounter(myCounter); System.out.println(myCounter.count); // Reveals 1, Oh, look! It changed! }

To simulate pass-by-reference like in C#, you can use wrapper classes or atomic references, more on them later.

Making Organic changes with Mutable Wrappers

To simulate pass by reference behavior, there's an alternative approach where we exploit Mutable Wrappers. Classes from the java.util.concurrent.atomic package, such as AtomicReference, will help you out here and provide thread-safe atomic operations.

class DataWrapper { public String data = "Original data"; } public static void changeData(AtomicReference<DataWrapper> ref) { ref.get().data = "New data"; // Here's your change, shiny and new! } public static void main(String[] args) { DataWrapper deadPool = new DataWrapper(); AtomicReference<DataWrapper> refPool = new AtomicReference<>(deadPool); changeData(refPool); System.out.println(refPool.get().data); // The output will be: "New data" }

Switching the object state, not the reference

Java allows methods to modify the state of an object referred by the reference copied. However, rebinding the copy of the reference to a new object will not affect the original reference. Cue in an example!

class ShiftingNumber { public int num; } public static void shiftNumber(ShiftingNumber sn) { sn.num = 10; // All hands on deck! We are shifting base! } public static void main(String[] args) { ShiftingNumber shNum = new ShiftingNumber(); shiftNumber(shNum); System.out.println(shNum.num); // You guessed it, it's 10! }

The change in the object's state is visible outside the method too because we modified its internals via the reference, just like bad stomach malaria - the symptoms show on the outside.

Look Inside: Understanding Object References

Java's approach to dealing with object references is like giving someone directions to a treasure chest. You can alter what's inside the chest alright, but you can't change the map to the treasure that was passed along.

Now, let's see what changing those maps really means:

  • Method boundaries: As with most methods (and politicians), declarations in method could be misleading. Reassigning references inside method scope does not affect the original reference outside.
  • Abandoned objects: Once the method execution is over, we have some objects that went out of scope. These are now candidates for garbage collection. Wipe them out!
  • The AtomicReference magic: Classes like AtomicReference serve as a foolproof container that allows atomic operations on the reference, thus mimicking pass-by-reference. They are our knights in shining armor in a multithreaded environment.

Potential booby traps in modifying object references

  • Lost in reassignment: If you try to modify the reference inside a method, you might get bamboozled when the original object outside remains unchanged.
  • Spying on shared objects: Java objects created in a method are accessible by all other methods within the class and can lead to unforeseen consequences if not handled properly. It's a public secret!
  • Racing around threads: Concurrent modifications can lead to unintended results. Hence Atomic references should be used to play safe during concurrency.