It's both, correct? Aren't objects passed by reference?
Campfire stories: Cup Size -- a story about variables
Pass-by-Value Please (Cup Size continued)
And if you liked those -- I'd seriously consider getting a copy of Head First Java. It's an awesome Java book that explains things in this fashion.
In the case of bar(), the int x is a primitive, so bar() works with its own local copy of the variable and modifies that. So, int a up in the main() method is not altered.
In the case of baz(), a reference to the Integer object b is passed to the baz() method. However, Integer is an immutable object--it provides no way of altering the int value it internally holds, like String--so inside baz() there is a new Integer object created with a new value, but then it's not returned by that method so it's simply dropped and lost.
In the case of bash(), a StringBuffer is a mutable String, and since it's an object it's passed by reference. Thus, appending the exclamation point alters the original object itself.
Originally posted by sever oon:
Java passes all objects by reference, and all primitives by value.
Howdy! This is definitely correct *thinking*, but the official Sun way of describing this is that Java passes *everything* by value, and that with objects, the value is... the value of the reference variable. We use the phrase "by value" to mean "by copy", and since both primitives and object reference variables are passed using a *copy* of the contents of the variables, we're able to say that even object references are passed by value.
What would be INCORRECT is to say that "Java passes objects by the *value of the object*". So a lot of people (including many books) prefer to say just what you've said, "Objects are passed by reference", but it doesn't fit with our terminology.
So here's how we say it...
"Java passes everything by value. If the thing being passed is a primitive, a copy of the value of the primitive is passed. If the thing being passed is an object reference, a copy of the value of the reference is passed. The value of the OBJECT is never passed, but the value of the REFERENCE is. Objects are never passed."
If Java had true pass-by-reference, then it could mean that you'd have a pointer to the variable itself, rather than a copy of the contents of the variable. And if you were allowed to have a pointer to the variable, then you could change the actual contents. That would mean a called method, for example, could change the caller's primitive variable that was passed! Or that a called method could not only change the object referenced by the passed object reference, but could actually reassign the reference itself... so that the caller's object reference suddenly contained a *different* reference value!
This is always a fun one--especially because I think everyone *means* the same thing--the big point is that objects are never passed. But it's the terminology that shifts. We use what James Gosling (father of Java) says, and his view is that everything in Java is pass-by-value.
References to objects are passed by value which may make it LOOK like it's pass by reference.
But try to assign a new object reference to the one passed and you'll notice that after returning from the method the old reference will still be there and the new one gone with the wind.
I kind of like Sever's statement:
Java passes all objects by reference, and all primitives by value.
But I also have to agree with Jeroen's statement that
Java is fully pass by value.
I think this confuses many beginners, also many C(++) programmers. It calls into question the nature of the pointers (albeit possibly indirect) used to produce and refer to instances of objects. The second statement is perfectly true if we accept that these indirect pointers are themselves objects. I see these pointers not all that different to pointers used in C, but for the extra level of pointing meaning that they cannot be used the way they are in C to walk through objects (and beyond). Otherwise they are references to objects on the heap.
Now the fact that I cannot change the value of an Integer wrapper object is really forced by the object being immutable, as Sever points out. I could easily define a class, say MutableInteger, which exposes the wrapped value, and not so easily add the functionality of the existing Integer class, or I could store an Integer inside MutableInteger and easily provide Integer functuality. This would practically be a pass by reference. Sure we are getting a copy of the pointer (value), but the real object we are looking at would be an instance of MutableInteger.
These discussions should really highlight the fact that "returning via the parameter list" is not really good programming practice and can cause hard to locate side effects. Much better to return a multifaceted object or reorganize along better OOP lines.
Just my tuppence worth! Have fun!
[ August 25, 2004: Message edited by: Eddie Vanda ]
Ok, of course you guys are technically correct. I have been brewing Java long enough to know this, I was just hoping not to confuse anyone. Besides, I think it's so confusing because while saying "Java is fully pass-by-value" is technically correct, it doesn't seem semantically correct to me. (In other words, I think the terms we are being forced to use are misleading and could be redefined to make things clearer.)
Why's that? Well, in my way of thinking, in Java when one passes an object to a method it is in fact passed by reference because the thing being passed is a reference to the object. When passing a primitive, it's passed by value because the value of the primitive is passed, but not that particular primitive itself. What C++ calls "pass-by-reference" ought to be called "pass-by-pointer" because that's what it really is...a compiler trick that short circuits the need to manually dereference pointers, but that's what's really going on underneath the covers.
I know this is not the terminology we're brought up with, but it makes everything so much clearer to think of it that way.
In this way, the distinction is always clear that in C++ there's really no such thing as a reference, and in Java there's really no such thing as a pointer.
(It's been a while since I wrote in C++, but I'm fairly certain that if a caller had an int* and passed it to bax(), and bax() incremented its local pointer y, the pointer itself has been passed by value so when bax() returns to the caller, the caller's int* would not have changed. Am I right?)
Now the real question: is there something conceptually wrong or inconsistent with this way of thinking that I've missed?
[ August 26, 2004: Message edited by: sever oon ]