Someone was wrong on the Internet, so I had to post a comment. Cross-posting here just so that I don't lose the text in case I ever need to tell someone else about this stuff. Quoting myself:

We need to pay attention to the difference between references and pointers, since that seems to be the root of the confusion. These two words don't mean exactly the same thing in different languages. As a compiler developer, I know that these things can be tricky for humans. I've seen more than a few bugs caused by misunderstanding all of this. 

Pointers are variables that (can) contain the value of an address. You can update that value to be anything though. For example, you can set a pointer to be the number 15. Or more commonly, you can set it to 0, which many languages including java grant a special name — null. Also, you can do arithmetic operations on the value contained in a pointer, like p=p+5. Hence, pointers can contain invalid addresses. Java lets you update variables containing addresses (a = new foo(); a = new bar();), and it lets you set them to be invalid addresses like 0 (a = null). Hence, I argue Java Object variables are pointers. The Java compiler (as far as I know) does not permit these pointers to be arithmetically manipulated (a = new foo(); a = a + 5;) but this is a limitation (feature) overlaid on what are, intrinsically, pointers. 

References are a very special kind of pointer, because the compiler puts very strict rules on them and grants them super-powers when it comes to certain operators. The most important (and most general) difference between references and pointers is that references can not be to arbitrary addresses, like null. They must always refer to an actual object. Moreover, references are fixed and unchanging once initialized, so once they refer to some object, they can never refer to another object. These two properties are fundamental to references in my view, and of course some languages vary in their definition slightly.

So what good are references, with all of these restrictions and limitations? Good Question! It gets to the heart of the debate. Because references can never be updated, and because they are always valid (i.e., never null or some other garbage,) the compiler can change the meaning of assignment and data reference. Remember how, with pointers, when you assign to them, you change the pointer itself?

int b = 10;

int * p = &b;

p = 5;

print(p, b); // prints 5, 10

Now p contains the value 5, which is an invalid address. But no matter, all we've done is updated the value of p. b is unchanged. This is by-value assignment. It is critical to understand this. Now lets look at by-reference assignment, which is similar to by-reference calling conventions:

int b = 10;

int &r = b;

r = 5;

print(r, b) // prints 5, 5

Because of the special properties of references, the meaning of the assignment operator is different. Of course, under the covers, both pointers and references are addresses. The words "pointer" and "reference" imply compiler features are at work, like pointer arithmetic and index operators in the pointer case, or modified assignment and guarantees about no nulls in the reference case.

The above is assign-by-value and assign-by-reference. call-by-value and call-by-reference are very similar:

int i = 42;

call_by_reference(i);

print(i); // prints 6

call_by_value(&i);

print(i); // still prints 6, even though we passed a pointer to the function up there

int * foo = &i;

pass_pointer_by_reference(foo);

// now foo is an invalid pointer, because the reference was assigned-to inside the function. i is unchanged still. 

void call_by_reference(int &r) { r = 6; }

void call_by_value(int *p) { p = 6; }

void pass_pointer_by_reference(int *&pr) { pr = 6; }

So what is java? Well, as mentioned, it seems to implement pointers and a by-value calling/assignment convention. I think it is patently obvious that java is pointer-heavy call-by-value language.