Here are some diagnostic examples for Java's argument passing semantics:
For an object type:
void changeIt(String s) {
s = "bye";
}
String s = "hi";
changeIt(s);
System.out.println(s); // would print "bye" for call by reference
// but actually prints "hi"
For a primitive type:
void changeIt(int i) {
i = 42;
}
int i = 0;
changeIt(i);
System.out.println(i); // would print "42" for call by reference
// but actually prints "0"
In fact, in both of those examples, the assignments within the changeIt
methods only affect the respective method's local variable, and the actual values printed will be "hi" and "0".
EDIT
And since the OP still doesn't believe me ... here's a diagnostic example to show that Java is call-by-value for mutable objects as well.
public class Mutable {
int field;
public Mutable(int field) { this.field = field; }
public void setField(int field) { this.field = field; }
public int getField() { return field; }
}
void changeIt(Mutable m, Mutable m2) {
m = m2; // or 'm = new Mutable(42);' or 'm = null;'
}
Mutable m = new Mutable(0);
Mutable m2 = new Mutable(42);
changeIt(m, m2);
System.out.println(m.getField());
// would print "42" for call by reference
// but actually prints "0"
By contrast, this example will give the same answer for both call by reference and call by value semantics. It doesn't prove anything about argument passing semantics.
void changeIt2(Mutable m) {
m.setField(42);
}
Mutable m = new Mutable();
changeIt2(m);
System.out.println(m.getField());
// prints "42" for both call-by reference
// and call-by-value
Trust me, I've been programming Java for > 10 years, and I've taught comparative programming language courses at university level.