No
But Java has references
Indeed. Java has "reference" values, also known as "pointers." Passing a reference (pointer) is not the same thing as passing "by" reference.
But that's just a quibble
No, it really isn't. Passing a reference and passing by reference give completely different behavior.
Prove it
Sure. Here's some example code.
String s = "Hello";
foo(s);
System.out.println(s);
When passing a reference value, that third line can only ever output "Hello" regardless of how the method foo(String) is implemented. If Java supported pass by reference, however, the output could be absolutely anything.
You're just quibbling over the terminology
If you want to communicate about programming languages you have to be very precise, otherwise you can't be understood. If you use the wrong terminology (deliberately or unintentionally) you will be misunderstood.
But passing references can achieve the same effect as passing by reference.
Yes. Similar, but not identical as the code above proves. Here's a similar effect to pass by reference achieved by passing a reference:
String[] s = new String[] { "Hello" }; foo(s); System.out.println(s[0]);
There the printed output could be anything.
So it's the same.
No, it's not the same. Those two bits of code are different precisely because it's not the same.
But I prefer the "pass by reference" terminology to the "pass a reference" terminology
Well I can't stop you. But it's wrong. How about "pass by pointer" which is unambiguous? Java "references" are called "pointers" by everyone else anyway, and the JLS refers to the values stored in reference variables as pointers anyway.
I guess. So can any languages do pass by reference?
Absolutely. In C++ you could write the first code example and not know what value was to be output.
But I could do that in Java too if I had my own String class
Not quite. In Java you would be mutating the object (java.lang.String is immutable). In C++ you can cause the variable s to have a different value - a pointer to a different object. That's just not possible in Java. There's a special syntax for C++ that allows you to declare a parameter as having reference type:
void foo(String& s) { s = String("Goodbye"); }
Why doesn't Java have this?
Does it matter? Use C++ if you really want this ability so very badly. I can't say I ever feel the pain of this "missing" feature. I do a lot of Java development and used to be a C++ developer. If you do find it to be a major problem then, well, you could always use C++ instead.
Update: What about C#?
C# supports pass by reference, although the inimitable Ian points out that you need to explicitly request pass by reference in the calling code AND the method implementation (omitting either would be a syntax error). This helps avoid the fallout of passing some vital variable to a pass by reference method without realising the possible consequences.
I read a book that said Java passes by reference
There are some books that incorrectly state this. It's still wrong. Sometimes they're fairly good books and the author let up for a moment with the terminology - other times they're bad books. For the most part if a book says this you should treat other things that it says with some skepticism too.
The JLS does not refer to "pass by reference" anywhere, and the JLS is quite literally right by definition since it defines the Java programming language.
You're wrong! Java DOES have pass by reference!
Sigh. Hello DaFei.