The real problem is that Java created needless confusion by calling its pointers references for purely marketing reasons.
This is silly; "pointer" and "reference" both had meanings before Java came along. If Java called pointers "names" instead of "references" it wouldn't mean that its function call semantics were pass-by-name either. And besides; if your argument is that we should use the Java terminology to describe all the aspects of Java under discussion, the fact that the all the Java designers make explicit that the function call semantics pass references as values, not objects as values.
"And your example fails to compare apples to apples. In Java Integer is an object, but int is not. You are confusing Java things with C++ things."
The argument applies if you use int in place of Integer just the same; or if you make a C++ Integer wrapper class analogous to the Java one. Any comparison here will of course be apples to oranges because C++ supports pass by reference and Java does not. The swap function is impossible to write in Java because it requires allowing called functions to change the values viewed in the caller, which is almost the definition of passing arguments by value.
"As you can see, Java is not C++, and so your C++ terms and definitions do not apply here. Thank you for playing. Move along."
Leaving aside the childish and insulting tone, the definition of "pass by reference" has nothing to do with C++; if the code were in perl it would still be pass by reference, because "pass by reference" has a meaning that exists outside of any particular programming language and describes a concept. Java function calls are not part of that concept; "there is exactly one parameter passing mode in Java - pass by value".
class Foo; void modify( Foo& x) { x.setBar(1);} ; <- pass by reference in C++.
class Foo; void modify( Foo x) { x.setBar(1);} ; <- pass by reference in Java.
Java spares you the & because Java only passes by reference.
Again, to argue the contrary, simply because it passes an object pointer by value, automatically, is to argue that C++ never passes by reference because it too takes the address automatically.
The fact is that Java passes by reference exactly as C++ does. However, even if this were not the case, it would also be completely acceptable for Java to refer to what it does as pass by reference simply because it chooses too. These things are object references. If I pass a java object reference, is it acceptable to say I'm passing by reference? If Java people want to say it is, then it is. Will the world end, for example, because the word "heap" means two different things in computer science? http://en.wikipedia.org/wiki/Heap OMG! Who is right?
My point is basically summed up here: http://xkcd.com/435/
You are where the physicist is standing. You insist that Java biologists are using your terms wrong while oblivious to the mathematician. You have your abstractions. Java has theirs.
Of course, maybe you're the chemist, and I'm the physicist (I still write assembly) and the hardware guys are the mathematicians. Whatever.
As for the insulting tone, yes its a character flaw. When someone makes a statement like "I'm really tired of hearing folks (incorrectly) state [whatever]", its insulting. Its especially insulting when its wrong. In an ideal world I'd be able to respond without resorting to responding in kind, but I'm flawed. Sorry. You're still wrong.
The Java code you give isn't an example of passing by reference because, while you can change the value that x points to in Java, you can't change x to point to something different. No java function can change its arguments; the example you gave has the java function changing something that its argument points to.
Your argument that Java people can call language features the same name as distinct language features is: a. dumb, because it's just "words mean whatever anyone wants them to mean", and b. doesn't come anywhere close to applying here; the quotation at the end of my last response: "there is exactly one parameter passing mode in Java - pass by value" is a direct quote from 'The Java Programming Language'. The authors of Java disagree with you.
More from them: "All parameters to methods are passed 'by value'. In other words, values of parameter variables in a method are copies of the values the invoker specified as arguments. If you pass a double to a method, its parameter is a copy of whatever value was being passed as an argument, and the method can change its parameter's value without affecting values in the code that invoked the method.
...
You should note that when the parameter is an object reference, it is the object reference - not the object itself - that is passed "by value." Thus, you can change which object a parameter refers to inside the method without affecting the reference that was passed. But if you change any fields of the object or invoke methods that change the object's state, the object is changed for every part of the program that holds a reference to it.
...
Some people will say incorrectly that objects are passed "by reference." In programming language design, the term pass by reference properly means that when an argument is passed to a function, the invoked function gets a reference to the original value, not a copy of its value. If the function modifies its parameter, the value in the calling code will be changed because the argument and parameter use the same slot in memory.
...
The Java programming language does not pass objects by reference; it passes object references by value. Because two copies of the same reference refer to the same actual object, changes made through one reference variable are visible through the other. There is exactly one parameter passing mode - pass-by-value - and that helps keep things simple."
Your last few paragraphs are beside the point; the question is not about which languages offer which levels of abstraction; the point is that different abstractions have different names and Java doesn't offer the abstraction named "pass by reference".
class Foo;
void Bar( Foo& somefoo) { ... }
It's easiest to illustrate this with code:
public class ValueHolder {
public ValueHolder(int value) { this.value = value; }
public int value;
public static ValueHolder THREE = new ValueHolder(3);
}
public class DoSomething extends TestCase {
public void passByValue(byvalue ValueHolder value) {
value.value = 1;
value = new ValueHolder(2);
}
public void testPassByValue() {
ValueHolder myValue = ValueHolder.THREE;
passByValue(myValue);
assertEquals(ValueHolder.THREE, myValue);
assertEquals(3, myValue.value);
}
public void passByReference(byref ValueHolder value) {
value.value = 1;
value = new ValueHolder(2);
}
public void testPassByReference() {
ValueHolder myValue = ValueHolder.THREE;
passByReference(myValue);
assertNotEquals(ValueHolder.THREE, myValue);
assertEquals(2, myValue.value);
}
public void passReferenceByValue(ValueHolder value) {
value.value = 1;
value = new ValueHolder(2);
}
public void testPassByValue() {
ValueHolder myValue = ValueHolder.THREE;
passByValue(myValue);
assertEquals(ValueHolder.THREE, myValue);
assertEquals(1, myValue.value);
}
}
Syntax is slightly made-up because Java doesn't have true pass-by-value or pass-by-reference for object, only pass-reference-by-value. But the test cases illustrate the expected semantics for each parameter passing mode.In each case, you're passing a mutable object containing a value to the function. In pass-by-value, you pass a completely new copy of the object in, so the mutation doesn't affect the original object at all, and then the reassignment obviously doesn't propagate back to the caller. In pass-by-reference, you pass in a reference, so the mutation changes the object in the caller's scope, and then the assignment reassigns the variable in the caller's scope to the new ValueHolder. It's this last part that pass-reference-by-value can't do: normal Java semantics let you mutate the object passed in, but you can't make the variable in the calling frame actually point to an entirely new object.
Make sense?
IBM has it wrong too then. In each of the examples provided, they dont "make the variable in the calling frame actually point to an entirely new object"
What actually happens is that the object (or value) that is pointed to by the reference is changed. Specifically, if you took the addresses of a and b before the call, and then after the call, you would see that the addresses have not changed. It is the contents that have changed. This is what happens it C++ in all cases. The only difference between C++ and Java is that Java is always pass by reference for objects and always pass by value for primitives.
Pass-by-reference does not mean "I can change the variable in the caller to now point to a new object". It means, if I modify the properties of the parameter, it is modifying the same object that the variable references. In contrast, if you do this in C++:
class Foo; void bar( Foo x ) { x.value++; } void main() { Foo y(0); bar(y); }
You will discover that y's value remains 0. That is pass by value.
class Foo; void bar( Foo &x ) { x.value++; } void main() { Foo y(0); bar(y); }
This is pass by reference. y.value is now 1. So now if this is Java:
class Foo; void bar( Foo x ) { x.value++; } void main() { Foo y(0); bar(y); }
Then y.value is now 1 - just like the pass-by-reference case in C++. So either IBM has it wrong, or you have it wrong.