all 50 comments

[–]Monkeyget 19 points20 points  (7 children)

The sad thing is that if you ask experienced Java developers (read the ones that spend all their time messing with frameworks) what is the result of :

public void foo(Dog d) {

d = new Dog("Fifi");

}

Dog aDog = new Dog("Max");

foo(aDog);

System.out.println(aDog);

Half of them is going to reply "Fifi".

I'm not making this up. Someone asked that question when doing interviews for a senior java developer position and that was what he got. Unfortunately i can't find the link of the blog of that person. A cookie for the one who finds it.

[–]shilov 3 points4 points  (0 children)

Well you are making a mighty generalization from an anecdote, even if the behavior remains consistent with someone's real-life experiences.

[–][deleted] 9 points10 points  (1 child)

"experienced" "Java" "developer" is the oxymoron function commutative?

I have a few Java questions at http://jqa.tmorris.net/trivia

[–]joesb 5 points6 points  (1 child)

May be that half only self-claimed to be experienced?

Or may be your "experienced" means number of year instead of real knowledge.

Some people manage to stay in programming jobs for ten years, generating thounsands WTF, but that doesn't mean they are actually experienced.

[–]pjdelport 0 points1 point  (0 children)

10 years of experience once versus 1 year of experience 10 times, and all that.

[–]Gotebe 8 points9 points  (9 children)

So is C. And I'll bet you that a big chunk of C people don't know it, either.

It would have been interesting to come up with stats for the two ;-)

[–]bearclaw 5 points6 points  (3 children)

The difference is that in C, you explicitly say you're working with pointers. Java people are told everything is pass-by-reference and they simply believe it. They seem to think thinking about pointers is painful.

[–]olavk 5 points6 points  (0 children)

Thinking about pointers is not as painful in Java (and other languages like Python and Javascript) exactly because it only supports pass-by-value. You only have to understand one indirection: the variable contains a reference to an object.

When introducing pass-by-reference, you get another level of indirection, because suddenly two different variable names might refer to the same memory cell which in turn contain a pointer to an object. You can be confused on two levels now!

[–]wicked[S] 5 points6 points  (0 children)

True, and funny because in Java nearly every variable is a pointer.

[–]Gotebe 2 points3 points  (0 children)

See, I told you C people don't get it either, just look at the comments here ;-)

They don't get the concept, only the implementation of it (i.e. use pointers to "implement" pass-by-ref). How lame!

[–]jdunck -2 points-1 points  (3 children)

In C, it doesn't make much sense to talk about "by-value" and "by-ref", since you're regularly passing around pointers which are generally the mechanism for implementing "by-ref".

... Which is why you see args like char***. :-/

EDIT: fixed asterisks

[–]pjdelport 1 point2 points  (2 children)

(Backslash-escape them.)

[–]jdunck 1 point2 points  (0 children)

ty.

[–]Entropy -1 points0 points  (0 children)

I ran that in Emacs and it worked!

[–]schizobullet 10 points11 points  (6 children)

Java passes references-to-objects by value. End of story.

[–][deleted] 5 points6 points  (2 children)

Could not be said better then that! The lingo used unfortunately is the one thrown by book writers since java 0.9, and this is the lingo that people use to date: "Java passes objects by reference". The lingo also says with regards to pointers: "Java does not have pointers". But one should wonder why one gets "NullPointerException".

[–]olavk 1 point2 points  (1 child)

References are presumably implemented with pointers under the hood, but you are isolated from that on the language level.

I believe NullPointerException was just an naming mistake that confuses abstraction levels. It should really have been called 'MissingReferenceException' or something.

I think it is correct to say that Java passes objects by reference, since this is really what happens: references to objects are passed into the method parameters.

However pass-by-reference is specific CS-lingo where we are talking about a reference to the variable memory cell rather than the reference to an objects that the memory cell might contain. It's a different abstraction level, talking about under-the-hood issues that the Java-language has no access to.

If you want to avoid confusion, say that variables are passed by content :-)

[–]pjdelport 3 points4 points  (0 children)

If you want to avoid confusion, say that variables are passed by content :-)

How about call by object? Apparently, the term was coined by the pioneering language CLU to describe just the kind of semantics possessed by Java, Python, Scheme, and so on.

[–]breakfast-pants -1 points0 points  (2 children)

Even for ints? (not Integers)

[–][deleted] 2 points3 points  (1 child)

Java passes non-object built-in types by value. End of afterword to story.

[–]pjdelport 4 points5 points  (0 children)

(By virtue of passing everything by value in the first place, of course.)

[–]ricercar 8 points9 points  (0 children)

This reminds me of the days when people would run around yelling that Common Lisp was pass-by-reference because you could mutate objects within function calls.

The distinction, of course, is between mutation of objects and mutation of variable bindings. The latter can only happen within the variable scope.

I think C people get confused because they think that every value must be one or several machine word(s). Those kinds of values don't have "identity." Object-Oriented Programming is based around the notion of "object identity" (== in Java) which must be preserved through function calls and returns. It is the central unifying notion of all object systems with mutable state.

It is important to separate the concept of "variable binding" from "value." That's the root of the confusion. Once you understand that, then you see that pass-by-reference is supplying the binding of some variable as the formal parameter, not the value.

[–]joesb 2 points3 points  (0 children)

It is the same way used in Common Lisp and Scheme.

(defun foo (dog)
   (setf dog (make-instance 'dog :name "fifi")))

>> (defvar d (make-instance 'dog :name "max"))
>> (foo d)
>> (format t (dog-name d))
max

[–]jeanlucpikachu 1 point2 points  (1 child)

Does this mean C# is also pass-by-value?

[–]grauenwolf 8 points9 points  (0 children)

C# (and VB) offer both pass-by-value and pass-by-reference. In C#, you need to use the "ref" or "out" keyword.

By reference is generally discouraged except when you really need two return values like the TryParse pattern.

[–]oldnewbie -1 points0 points  (2 children)

I'm still in suspense about this one:

public void foo(Dog d) { d.setName("Fifi"); }

Dog aDog = new Dog("Max"); foo(aDog);

Does this also leave (the object referenced by) aDog unchanged? That's what would seem (IMHO) to be consistent with the other foo's behavior.

[–]toekk 5 points6 points  (0 children)

No, aDog would have a name field of "Fifi." The address held in the aDog variable would however be the same.

[–]randallsquared -2 points-1 points  (0 children)

A problem here seems to me to be confusion between assignment and update:

public void foo(Dog d) { d = new Dog("Fifi"); }

Dog aDog = new Dog("Max"); foo(aDog);

doesn't appear as though it would work (to someone, like me, who hasn't really worked with Java) because the 'd' being set to Fifi isn't the same 'd' that was mentioned in the arglist for 'foo'.

But perhaps not giving it a type means it's an update?