Java uses quite a few tricks to achieve what other languages have while still being user-friendly, and this is a great example. Although, after reading the article, I was kinda confused. For anyone having troubles understanding, if objects were pass-by-reference, this would be possible:
void method(String string) {
string = "second";
}
String string = "first";
method(string);
System.out.println(string); //prints "second"
Rather than passing the actual reference to that object, a new reference is created (the formal parameter), which then references the object. So saying object references are pass by value is not true, since a reference value is a pointer to the object, and passing the reference value (pointer) is passing by reference. If you wanna get literal with it, object identities are (currently) pass by value. Another thing that confuses some developers is how generics are a compile time illusion, and all generic types are converted to Object (type erasure) once compiled. This is why you cannot have "void method(List<String>)" and overload it with "void method(List<Integer>)", since both compile to the same after erasure.