Java Doesnt Pass By Value

Java appears to pass objects by reference instead of by value. That is, when mutable objects are passed to a method as parameters, any changes made to those objects by the method persist beyond the method call.

What's really happening is that objects are always held by reference in java -- never by value -- and the references are, indeed, being passed by value. Since objects in java are never held by value it is convenient to ignore the implementation details and just say that objects are passed by reference in java. Some people think that's the wrong thing to do since there is a semantic difference between passing an object by reference and passing an object reference by value. Others don't believe it is because there is no observable difference in behavior between the two.

Is there a difference? Yes. In both cases a method can cause side effects to an object defined outside of its own scope so there is a similarity. However, the semantics for an object are different than the semantics of a reference. Specifically assignment between objects changes the value of one of the objects, while assignment between references changes the value of one of the references -- not the object it points to. Similarly, the == operator tests whether two references point to the same object, not whether two objects have the same value. C++ programmers can easily become confused by java references because they act just like C++ references in all ways except for assignment and equality testing, where they act like C++ pointers instead.

-- SunirShah, WayneConrad, PhilGoodwin, DavidSarahHopwood (summarized by PhilGoodwin)


JavaPassesByValue, truly. The confusion is only in that Java redefined the word "reference", when actually they mean "a safe kind of pointer", which is not what everyone else means by "reference" in the phrase "pass by reference".

According to the non-Java definitions of terms, there is no confusion, as illustrated by the impossibility of writing a swap() function.

See JavaPassesByValue for more.


Alternative Semantics

So if we admit that JavaPassesByValue then we also have to admit that java can't pass objects at all -- only references to objects which isn't the same thing. This doesn't seem like much of a limitation at first since the called method can make a private copy of the referenced object to operate on if that's what's needed. That is to say that pass by value semantics for objects can be implemented in terms of pass by value semantics for references -- just call "clone". There are two places where this falls down: untrusted modules and remote objects. Untrusted modules can modify your object even though you don't want them to and reference semantics are expensive to implement for remote objects if you don't need them (you have to serialize the object and send it over the network an extra time). You can protect yourself from untrusted modules by clone()ing objects before passing them in or by passing only immutable objects (either by using ImmutableValues or ImmutableWrappers).

Conversely java doesn't allow primitive values to be manipulated by reference at all so, while objects can be manipulated through reference semantics, primitives cannot. One ramification of that is that non-public object fields cannot be changed by any method outside of the object that holds them even with that object's permission. Some people feel that designs that require object fields to be manipulated by reference or objects to be passed by value are inherently suspect.

-- MartinPool, SunirShah, DiniMorelli? (summarized by PhilGoodwin)

Deciding what we might do with ValueSemantics if we had them is probably a subject for another page, but, briefly in C++ ValueSemantics allow: composed objects that can be allocated and initialized in a single step, no need for immutable ValueObjects, and user-defined assignment semantics.

Note that user-defined assignment semantics can be supported in a different (and arguably more useful) way using GeneralizedReferences or equivalent. -- DavidSarahHopwood

I have found that having a wider range of semantics available for both primitive types and objects introduces more potential complexity and more opportunities for bugs, but it also results in a richer and more expressive language that allows programs to be written that are actually easier to understand and maintain. -- PhilGoodwin


See AlternativesToPassByReference, ReferencesValuesIdentitiesAndVariables.


ThreadMode below -- preserved mainly for historical context, since all the arguments are already given above and at JavaPassesByValue.



"Java is a pass by value language. However it's common to pretend that we have both pass by value and pass by reference."

Despite Gosling's insistence on this matter, I fail to see how anyone can defend the position that passing a reference to an object does not constitute pass-by-reference. That you cannot pass references to a few things (parameter memory, local variable memory, and instance variable memory) is mildly interesting and somewhat precludes the amusing notion of "out" parameters. Those unimportant limitations don't make Java a pass-by-value language. Next time you pass an object into a method that unexpectedly alters it, tell me again that Java is pass-by-value.

Note how any responses below arguing that Java truly is a pass-by-value language will rely on immutable types like String. Those arguments fall apart when you plug a mutable type into the same example.

The counter example in JavaPassesByValue would work as easily with a mutable object. Hopefully this argument has been suitably put to rest on both pages. This is far more than the academic distinction that you make it out to be, and understanding these rules is fundamental in not introducing horrible bugs into real world programs.


All you have is a reference, and you pass its value. If you passed a reference to it, the called method would have a reference to a reference. "Pass by value" is exactly as meaningful a description for this as "pass by reference" is. Really, the C people should call their behaviour "pass by copying" or something and save the rest of us this confusion. They're the ones doing Really Odd Stuff -- DanBarlow

Actually, there is a difference. We get a reference object by value in Java. If values were passed by reference you could do something like the following:

 void foo( String bar )
 {
bar = "foo";
 }

String bar = "bar"; foo( bar );

System.out.println( bar );

Since Java is pass by value, "bar" is printed out rather than "foo". It seems pretty simple and straight forward to me. I don't think anyone was accusing Java of being odd in this regard. It is just a statement of fact. The only nice thing (in this regard) about CeePlusPlus over Java is that you can declare an argument (or method) as constant.


Nevertheless, I have interviewed quite a few candidates (claiming to be "familiar" with Java) who got this wrong, they said "foo" will be printed.

You can declare a parameter constant in a method by adding 'final' to the parameter declaration. This would make the above program syntactically incorrect. Arguably, parameter variables should always be final to prevent exactly this type of mistake. This is the same as declaring a parameter 'const' in a method declaration, but not the same as declaring an argument as 'const' in a method invocation (Java does that behaviour by default).

No, not really. 'final' is not at all like 'const'. Final does not prevent mutating members from being called. In CeePlusPlus, declaring a method or argument as const prevents any non-const (i.e. mutating) methods from being called.

Except for the special case when the parameter type is a primitive. In this situation final is just like const. In other words, final is const, for very small values of const.


See JavaFinalArguments

I don't see how final fits into this discussion. You mean as a subtlety of Java or some how being like const declarations in CeePlusPlus. If the latter, I'd have to argue that they are completely different -- worlds apart.


If all classes in Java defined immutable objects, Java could correctly be described as a pass-by-value language. But that is far from so. In truth, very few Java classes actually do define immutable objects.

Your own example adjusted to use a more typical class for the method parameter clearly demonstrates that the Java language exhibits pass-by-reference semantics (in addition to the pass-by-value semantics not shown.)

 void foo( PhoneNumber number )
 {
number.setAreaCode("312");
 }

PhoneNumber bar = new PhoneNumber("800", "555-1212"); foo( bar );

System.out.println( bar ); // prints "(312) 555-1212"


Let's distill...

All you have is a reference, and you pass its value.

 = you have a reference and you pass its value
 = you pass the value of a reference that you have
 = you pass the value of a reference
 = you pass a reference

If you can pass a reference -- or, as you say, the value of a reference -- clearly you have pass-by-reference.

Or shall I make the absurdity more glaring? If you can pass a reference, you can pass by reference.


Okay then, how about this:

 void foo( PhoneNumber number )
 {
    number = new PhoneNumber("312", "555-1212");
 }

PhoneNumber bar = new PhoneNumber("800", "555-1212"); foo( bar );

System.out.println( bar ); // prints "(800) 555-1212"

Still think you really have pass by reference?

Yes, of course. To be able to change what object "bar" points to, you would need a reference to the reference, which Java can't give you without encapsulating in some object or array. In C++: -- Points to? This is an even more confused statement. Bar is an object, not a pointer, that you claim is being passed by reference. If this were so, you could change. But it is actually a reference being passed by value. Hence you cannot change the actual variable "bar" within the function, only its contents.

 void foo(PhoneNumber &number*) {
    number = new PhoneNumber("312", "555-1212");
 }

PhoneNumber *bar = new PhoneNumber("800", "555-1212");

foo(bar);

cout << *bar << endl;


Let me try another example:

 void foo( PhoneNumber number )
 {
     number = new PhoneNumber("512", "555-1212");
 }

PhoneNumber bar1 = new PhoneNumber("312", "555-1212"); PhoneNumber bar2 = bar1;

foo( bar2 );

if (bar1==bar2) { System.out.println("pass a reference by value"); } else { System.out.println("pass a reference"); }

"pass a reference by value" gets printed, because bar1 and bar2 are references to the same object.


Uh.... ImConfused?. Can anybody explain to me exactly when Java will "pass by reference" (whatever that is) and when it will "pass by value"? As far as I can tell, in these examples the so called "pass by value" behavior -which, as I take it, means that the object in the calling function isn't changed after calling foo()- occurs when trying to assign the object to a newly instantiated function. In these cases, bar = "foo" and bar = new Phone'Number(). When I say bar.areacode = "312", that's okay. As far as I can tell, declaring the new object doesn't work because we're incorrectly assuming that a reference itself is being passed. If that were true, if the value of the reference were changed in foo(), say, by assigning it to a new object, then the reference in the calling function would point to the new address. (Sorry if that sentence makes no sense, I'm tired). However, the reference in foo() will always point to the same address. So calling bar.areacode() works because the address being pointed to in the calling function and in foo() still agree. Is this right?

Hmmm... But I'm still confused by the last example. Help? - JasonEspinosa

That's because the last example is confusing and confused. "Pass by reference" has always meant passing the value of a reference to something. "Pass by value" has always meant passing a copy of the something. When we say "value", we're talking about an object's value, not an object's identity (which is what the "value of the reference" is).

Java always passes by reference. When immutable objects are passed, or when the called function refrains from modifying the state of argument objects, then the difference is difficult for the caller to detect. (It can be detected if copy-construction of the objects has side effects - but now we're not in Java-land anymore, since Java doesn't do such automatic copying.) The distinction is only important when the called function actually modifies the state of an object it receives. The terms "by reference" and "by value" are well understood and predate Java by a good bit, and it's unfortunate that discussions of Java often try to redefine the latter.

The loss of by-value semantics is not great, but combined with the lack of const qualifiers, it means that Java loses a particular type of declarative safety. -- DanMuller


> Or shall I make the absurdity more glaring? If you can pass a reference, you can pass by reference.

"a" and "by" are different words for me. -- Jens



CategoryJava

hi my name is David. 'am a new in java and i just read this page yesterday. I wrote a test this morning about the debate: that java does not pass by value. I would like to share the results of my test.

 public static void main (String[] args) {
 PhoneNumber? bar1 = new PhoneNumber?("312", "555-1212");
 PhoneNumber? bar2 = bar1;

foo( bar2 );

if (bar1==bar2) System.out.println("pass a reference by value"); else // prints pass arefrence by value System.out.println("pass a reference"); if (bar1.equals(bar2)) System.out.println("... contain the same value");
else // prints ...contain the same value
System.out.println("... contain different values");}

}
PhoneNumber? bar2 = bar1; The above line is called aliasing i.e bar2 has become an alias of bar1. This means that bar2 now points to (or refers to (or references)) the same object bar1 references and any changes made to bar1 after aliasing affects bar2 and vice-versa.



Hello everybody, my personal understanding is that java has a single behaviour:


EditText of this page (last edited November 13, 2014) or FindPage with title or text search