Too often I hear that languages such as C and Java have pass-by-reference by virtue of the fact that for objects and pointers, the address of the object is passed as a formal parameter rather than the object itself. Coming from a compilers background, this interpretation makes me cringe. What’s more amazing is that I continue to meet Java Architects and experienced programmers who throw around these definitions so informally. This misconception is further exasperated by authors like Bruce Eckel, who mutate the definitions in an attempt to simplify it. In Thinking in Java, Eckel admits this distortion of terms:
One could argue for the precision of such convoluted explanations, but I think my approach simplifies the understanding of the concept without hurting anything.
The fact of the matter is, the formal distinctions between pass-by-value and pass-by-reference are critical in fully understanding the intricacies of the language and why Java behaves exactly the way it does in certain contexts. Indeed, having nearly four years of experience teaching object-oriented programming, I’ve found that students who use the fuzzy definition, initially, have a clearer understanding of what’s going on but are hurt in the long run when using languages where the pass-by-reference mechanism is not so well abstracted. Even Eckel hints that his informal definitions work well for Java, but not necessarily for other true pass-by-reference languages:
There are those who say "clearly, it’s a pointer," but this presumes an underlying implementation. Also, Java references are much more akin to C++ references than pointers in their syntax. The language lawyers may claim that I’m lying to you, but I’ll say that I’m providing an appropriate abstraction.
In formal language theory, the definitions of pass-by-value and pass-by-reference are indeed more complicted, but not by much. I’ll use the definitions from Advanced Programming Language Design by Raphael A. Finkel to illustrate:
- In pass-by-value, the value of the actual parameter is copied into the formal parameter at invocation. Value mode is the most common parameter- passing mode. Some languages, like C, provide only this mode.
- The L-value of the formal parameter is set to the L-value of the actual parameter. In other words, the address of the formal parameter is the same as the address of the actual parameter. Any assignment to the formal parameter immediately affects the actual parameter. FORTRAN only has reference mode, and reference mode can be simuted in C through the use of pointers.
I think it’s time to get it straight. Java is strictly pass-by-value, even by Sun’s own admission. Yet, despite this evidence, something inside me tells me that I’m not quite right either. Perhaps Bruce Eckel said it best in the first edition of his text. What we really need is a new term: pass-by-handle.