36 comments

[ 4.6 ms ] story [ 87.1 ms ] thread
These kind of discussions is a symptom. Too few programmers have a clear mental picture of what goes on below their programming language.
I think also they don't have a clear understanding of what each term really means.
In C++, pass-by-reference means the method gets a reference to the thing. Pass-by-value means the method gets a copy of the thing.

Do these terms mean something different in Java? Again, I'm not a big Java dev, but I am interested in why there's such a big debate on this topic.

In C++, I typically pass-by-reference when I need to change the thing. When I don't need to change the thing (but it's expensive to copy) I pass by const reference so the thing cannot be changed, but is still efficient.

I seldom pass-by-value unless it's a primitive type (int, char, etc.).

It's also a symptom of zooming way in on one context and ignoring another, or just general annoying pedantry.

From the perspective of an object being passed to a method, Java is pass by reference. No copy of the object is made.

From the perspective of the implementation of methods, Java is pass by value, with the "value" representing any "object" involved being a pointer to that object.

Most of this argument seems to be people choosing one view of this duality and screaming that the other side is stupid and wrong. It's a tedious and annoying thing to see play out (although nowhere near as bad as your average "static vs dynamic typing" debate).

I think the difference is somewhat more important than you give it credit for.

If Java was truly pass-by-reference, then certain things that are not currently possible would be. It would make some existing code pretty silly frankly.

Do you have any good examples? Because I never could come up with a good one.

Probably 99% of the reference usage I've seen (all in C++, fwiw) could be about as easily accomplished with pass-by-sharing through pointers. The actual valid uses never seemed worth the nasty copy constructor bugs created by people mistaking reference semantics for pointer semantics.

At this point I gave up on "true" references so long ago that I tend to fall in with everyone else and call pointer-based sharing "pass by reference". I suppose I should amend my initial comment to specify that most of the team "pass by reference" is really "pass by sharing (through pointers)", but I'll wait on that until something convinces me that true references shouldn't go the way of dynamic scoping.

What about primitive variables, like "int"? If Java passed the variable reference (and not a copy), we should be able to modify it
Yes, if it did that we would be able to modify it (and have those modifications reflected outside function scope). It doesn't, so we aren't. Primitives add complexity to many aspects of Java, calling semantics being one of them.

I'd rather they'd went the route of forcing you to always use wrapped primitive types, but it's hard to fault the Java designers on that decision, especially when you consider the context of the time when it was made.

Weird. It's pass by ref for objects and pass by value for primitives. Why the flame war?
It's a war over semantics. Everyone agrees that primitives are pass-by-value, but when you pass an object, is that pass-by-reference because you're passing a reference to the object, or pass-by-value because you're passing the reference by value?

It's like the Java equivalent of airplane-on-a-treadmill.

There isn't any semantic ambiguity. The phrase "pass by reference" has a specific meaning. Java does not support pass by reference. Here's a quick test to see if your language uses pass by reference (when translated into Java, it will output "pass by value"):

    function f(x, y) { x = y }
    a = new A()
    b = new A()
    assert(a != b)
    f(a, b)
    if (a == b) {
        print('pass by reference')
    } else {
        print('pass by value')
    }
Yes, you're right, but the argument is still about semantics. Java programmers don't think in terms of passing a reference, they think in terms of passing an object (which happens to be done by passing a reference to it).

There's a correct answer to airplane-on-a-treadmill too, but that doesn't mean it's not an argument about semantics. Please let's just stop this here before this thread becomes like that other thread.

Assumes equivalence is referential equivalence, and not overwritten. Of note, in some languages where there are immutable strings (e.g. java I believe) there is only "one true string" for each string (of course this isn't directly relevant to the example code given above). This means "var a = "test"; var b ="test"; assert(a==b);" holds true for referential equality.
Which depends highly on the semantics of the == and = operators.

So if in java you decided to create an assign method (cuz remember operators are evil in java) and overrode equals then you could create such a situation in which it would return pass by reference.

Plus the equals operator in java is kind of f'ed anyways as it is.

Conversely if the language was pass by value (or not retarded) then code such as this should work.

  function f(x, y) { x == y }
    a = new String("foo");
    b = new String("f").append("oo");
    assert(a != b)
    if (f(a, b)) {
        print('pass by value')
    } else {
        print('pass by reference')
    }
(comment deleted)
It's a "war over semantics" only insofar as is my claim that "a dog is a plant." Using the standard, well-accepted definitions of terms in programming language jargon, Java is pass by value.

You can make the semantic argument that the terms "pass by value," "pass by reference," etc. have meanings other than the standard, well-accepted ones, and indeed that would be a "war over semantics," but what's the point? Similarly, I could argue that the definition of "plant" is "something with four legs," but what's the point?

That's just the thing: It's never pass by ref. References are passed by value.

If it were pass by ref, you could make a parameter point to a different object and it would still be visible after the method had returned.

It's not. In java the object's reference is passed by value.

There is a difference between passing an object by reference and passing the reference of the object by value. In the first case caller and callee share the same pointer to the same object while in the latter case each have a different pointer to the same object.

This article explains it very well : http://javadude.com/articles/passbyvalue.htm

Surely then, passing an object by reference is just passing the reference to the reference to the object by value?

It's references all the way down!

To take it to a lower level, we're passing a string of binary digits to the function. This happens either through a register, or through the stack. The function then has to decide what to do with it - either it uses it as the value of something, or it takes it as a memory address and derefences it. It can then repeat this last step for as many levels of indirection as it wishes.

It's clearer in C.

void f(struct object a); // Pass struct by value void f_(struct object* a); // Pass struct by reference, pass reference by value void f__(struct object a); // Pass reference to struct by reference, pass reference to reference to struct by value void f________struct object a); // What the hell are you doing? You've created a monstrosity

Primitives are cheap to copy, objects may not be.

Edit: I've never used Java that much. My experience with passing things to functions/methods is primarily in C++. When I say primitive types, I mean char or int.

I get a sick kick out of telling devs new to Java this when they run across it:

"Java is ALWAYS pass-by-value...", they nod, "...including OBJECT REFERENCES."

"What?"

My faith in mankind dies a little with every Java project we kick off...

And people ask why...

(comment deleted)
I'm the original designer for TheServerSide.com and .net logotypes. Originally the entire websites, but only the logotypes and headers remain. They're over a decade old, I'm getting nostalgic whenever I see them. It is amazing that the logotypes still survive.

Sorry for OT.

It's pass by value for primitives and pass by reference for objects. But it depends on what you call a reference. If all java objects would be immutable, you could say it's pure pass by value, but since you can alter the original object's state in the method, I call it pass by reference.

Before downvote: please explain, thank you.

...except that when methods are implemented a pointer to the "object" is what gets handed over. The narrow distinction that this pointer is passed by value makes some people feel exceedingly clever, despite the fact that the semantics of pass-by-reference in respect to the object itself are preserved.
Get a metaphorical microscope and focus in on call semantics in Java. Arguments no matter what their type are pass by value. So then What are you allowed to pass as arguments to a function in java? Primitive types, it is impossible to pass an object to a function in Java. Then what actually happens when people claim they are passing an object to a function in Java? It is passing a primitive type of type object reference to the function. It is doing so by value.
You're completely wrong, sorry.

Pass by reference means you change the value of a variable passed from the caller's context. You can't do that in Java.

(comment deleted)
Java is pass by value with mutable objects. Pass by reference is a different thing.

I think Java causes this confusion because it's so restrictive about what you can do with pointers. In C, the difference between a struct and a pointer to a struct is very clear. In Java, the fact that X x = new X() stores a pointer is sort of invisible.

should be chlorinate, not pollinate, we need less idiots, not more
(comment deleted)
Why is passing a reference by value so hard to understand?
Because, as Joel Spolsky said once, some people are born without the part of the brain that understands pointers.