Aug 5, 2009

Call-by-value Vs Call-by-reference in Java

The terms "Call-by-value" semantics and "Call-by-reference" semantics have very precise definitions, and they're often horribly abused when folks talk about Java. I want to correct that... The following is how I'd describe these

Call-by-value
The actual parameter (or argument expression) is fully evaluated and the resulting value is copied into a location being used to hold the formal parameter's value during method/function execution. That location is typically a chunk of memory on the runtime stack for the application (which is how Java handles it), but other languages could choose parameter storage differently.

Call-by-reference
The formal parameter merely acts as an alias for the actual parameter. Anytime the method/function uses the formal parameter (for reading or writing), it is actually using the actual parameter.

When you call a method by reference, the callee sees the caller’s original variables passed as parameters, not copies. References to the callee’s objects are treated the same way. Thus any changes the callee makes to the caller’s variables affect the caller’s original variables. Java never uses call by reference. Java always uses call by value.

How do you fake call by reference in Java, or more precisely, how can a callee influence the values of it’s caller’s variables?

* Use a holder/wrapper object passed to the callee as a parameter. The callee can change the object’s fields. That object may be as simple as an Object[]. In Java, a callee may change the fields of a caller’s object passed as a parameter, but not the caller’s reference to that object. It can’t make the caller’s variable passed as a parameter point to a different object. It can only make its local copy point to a different object. A holder class is just a class with fields to hold your values. It has no methods other than accessors for the fields.

* Have the callee return the new values, perhaps wrapped in an holder class or Object[], and have the caller store them away somewhere.
* Communicate via a static or instance variable visible to both caller and callee.
* Use a delegate object. The callee calls its methods to save the results for the caller.

Dale King points out that attempts to fake call by reference are usually a sign of poor object-oriented design. A function should not be trying to return more than one thing. He uses the term thing because it is proper to return more than one value (e.g. returning a Point that contains two values). If you are trying to return two values, the test he like to apply is whether you can come up with a logical name for the values as a group. If you can’t, you had better look to see if maybe you what you have is really two functions lumped together.

Java is strictly Call-by-value