And who has the authority to decide?
Edit: Apparently I haven't succeeded in formulating my question well.
I am not asking how Java's argument passing works. I know that what looks like a variable holding an object is actually a variable holding a reference to the object, and that reference is passed by value.
There are lots of fine explanations of that mechanism here (in the linked threads and others) and elsewhere.
The question is about the technical meaning of the term pass-by-reference. (End edit)
I am not sure if this is the right kind of question for SO, apologies if not, but I don't know a better place. Much has already been said in other questions here, for example Is Java "pass-by-reference" or "pass-by-value"? and pass by reference or pass by value?, but I haven't found an authoritative answer to the question what the term means.
I have thought that "pass by reference" means "pass a reference (usually a pointer) to the object", so the callee can modify the object the caller sees, while "pass by value" means copying the object, and letting the callee have fun with the copy (obvious problem: what if the object contains references, deep copy or shallow).
Sing the FW turns up lots of places saying "pass by reference" means just that, here there's some argument that it means more, but the definition still reads
A ParameterPassing mode where a reference (or if you want to be politically incorrect, a pointer) to the actual parameter is passed into the formal parameter; when the callee needs the formal parameter it dereferences the pointer to get it.
I haven't found many places giving a stronger definition for the term, on this page, I found "The lvalue of the formal parameter is set to the lvalue of the actual parameter." and, if I understand correctly, the same definition is used here ("The formal parameter merely acts as an alias for the actual parameter.")
In fact, the only places I found where the stronger definition is used are places arguing against the notion that in Java, objects are passed by reference (that may be due to my lacking google-fu).
So, if I got things straight, pass-by-reference
class Thing { ... }
void byReference(Thing object){ ... }
Thing something;
byReference(something);
according to the first definition would roughly correspond to (in C)
struct RawThing { ... };
typedef RawThing *Thing;
void byReference(Thing object){
// do something
}
// ...
struct RawThing whatever = blah();
Thing something = &whatever;
byReference(something); // pass whatever by reference
// we can change the value of what something (the reference to whatever) points to, but not
// where something points to
and in that sense, saying that Java passes objects by reference would be adequate. But according to the second definition, pass-by-reference means more or less
struct RawThing { ... };
typedef RawThing *RawThingPtr;
typedef RawThingPtr *Thing;
void byReference(Thing object){
// do something
}
// ...
RawThing whatever = blah();
RawThingPtr thing_pointer = &whatever;
byReference(&thing_pointer); // pass whatever by reference
// now we can not only change the pointed-to (referred) value,
// but also where thing_pointer points to
And since Java only lets you have pointers-to-objects (limiting what you can do with them) but doesn't have pointers-to-pointers, in that sense, saying that Java passes objects by reference is totally wrong.
So,
- Have I adequately understood the above definitions of pass-by-reference?
- Are there other definitions around?
- Is there consensus which definition is "the correct one", if so, which?
Who has the authority to decide? Nobody, and everybody. You decide for yourself; a writer decides for his or her book; and a reader decides whether to agree with the writer.
To understand the term, one needs to go under the hood of the language (and explaining them in terms of C code rather misses the point). Parameter passing styles refer to mechanisms that compilers typically use to create certain behaviour. The following are usually defined:
(A note of terminology: a parameter is the variable defined in the subroutine, an argument is the expression that is used in a call.)
Textbooks usually also define pass by name, but it's rare and not easy to explain here. Pass by need also exists.
The importance of the parameter passing style is its effect: in pass by value, any changes made to the parameter is not communicated to the argument; in pass by result, any changes made to the parameter are communicated to the argument at the end; in pass by reference, any changes made to the parameter are communicated to the argument as they are made.
Some languages define more than one passing style, allowing the programmer to select their preferred style for each parameter separately. For example, in Pascal, the default style is pass by value, but a programmer can use the
var
keyword to specify pass by reference. Some other languages specify one passing style. There are also languages that specify different styles for different types (for example, in C, pass by value is the default but arrays are passed by reference).Now, in Java, technically we have a language with pass-by-value, with the value of an object variable being a reference to the object. Whether that makes Java pass-by-reference where object variables are concerned is a matter of taste.
If you are familiar with C, perhaps the following analogy explains how Java works. This will be true only for objects of class-type (and not fundamental type).
In Java, we can have a variable and pass it to a function:
In C, this would look as follows:
In Java, variables of class-type are always references, which in C would be most faithfully mapped to pointers. But in function calls, the pointer itself is passed by copy. Accessing the pointer as in #1j and #1c modifies the original variable, so in that sense you are passing around a reference to the variable. However, the variable itself is only a pointer, and it itself is passed by copy. So when you assign something else to it. as in #2j and #2c, you are only rebinding the copy of the reference/pointer in the local scope of
f
. The original variable,a
orw
in the respective examples, remains untouched.In short: Everything is a reference, and references are passed by value.
In C, on the other hand, I could implement a true "passing by reference" by declaring
void v(struct Foo ** r);
and callingf(&w)
; this would allow me to changew
itself from withinf
.Note 1: this is not true for fundamental types like
int
, which are wholly passed by value.Note 2: A C++ example would be a bit tidier since I could pass the pointer by reference (and I didn't have to say
struct
):void f(Foo * & r) { r = new Foo; }
andf(w);
.