55

Possible Duplicate:
Is Java “pass-by-reference”?

I found an unusual Java method today:

private void addShortenedName(ArrayList<String> voiceSetList, String vsName)
{
     if (null == vsName)
       vsName = "";
     else
       vsName = vsName.trim();
     String shortenedVoiceSetName = vsName.substring(0, Math.min(8, vsName.length()));
     //SCR10638 - Prevent export of empty rows.
     if (shortenedVoiceSetName.length() > 0)
     {
       if (!voiceSetList.contains("#" + shortenedVoiceSetName))
         voiceSetList.add("#" + shortenedVoiceSetName);
     }
}

According to everything I've read about Java's behavior for passing variables, complex objects or not, this code should do exactly nothing. So um...am I missing something here? Is there some subtlety that was lost on me, or does this code belong on thedailywtf?

Community
  • 1
  • 1
Troy Nichols
  • 1,234
  • 1
  • 13
  • 17
  • 2
    Heh, write a function that swaps two `int`s :) Yep, switch to C# :-p – Mehrdad Afshari Apr 27 '09 at 20:34
  • 1
    Mehrdad: Just use Integer rather than int. – Andy Apr 27 '09 at 20:39
  • @Andy: Wasn't bashing Java that much. I know it's possible and not a big issue. Mostly meant as an educational joke ;) – Mehrdad Afshari Apr 27 '09 at 20:41
  • 3
    isn't Integer immutable? – user85421 Apr 28 '09 at 00:08
  • 2
    @Carlos Heuberger: Yes, but you can get around it with a one-element int[] instead. – Michael Myers Apr 28 '09 at 00:11
  • @mmyers: my comment was meant as reply to Andys comment. – user85421 Apr 29 '09 at 08:48
  • @Carlos: my comment was meant as a reply to your comment, which was meant as a reply to Andy's comment. ;) What I mean is that you can write a function that swaps two ints, but only if you first wrap them in an object. Since arrays are objects, two one-element arrays (or one two-element array) will do the trick. – Michael Myers May 15 '09 at 21:31
  • 3
    Wrapping (in Integer or an array) isn't creating pass-by-reference semantics. You're still passing by value; you're just passing a pointer to the wrapper or array. – Scott Stanchfield May 22 '09 at 14:25
  • See my article, "Java is Pass-by-Value Dammit!" http://javadude.com/articles/passbyvalue.htm – Scott Stanchfield Apr 27 '09 at 21:52
  • Java is an object oriented language and so you may consider, what happens to objects: Java passes Objects by Reference. Reference is an anchor to an object and has in this context not too much impact on the behavior. – Sam Ginrich Jan 12 '22 at 13:04

6 Answers6

112

As Rytmis said, Java passes references by value. What this means is that you can legitimately call mutating methods on the parameters of a method, but you cannot reassign them and expect the value to propagate.

Example:

private void goodChangeDog(Dog dog) {
    dog.setColor(Color.BLACK); // works as expected!
}
private void badChangeDog(Dog dog) {
    dog = new StBernard(); // compiles, but has no effect outside the method
}

Edit: What this means in this case is that although voiceSetList might change as a result of this method (it could have a new element added to it), the changes to vsName will not be visible outside of the method. To prevent confusion, I often mark my method parameters final, which keeps them from being reassigned (accidentally or not) inside the method. This would keep the second example from compiling at all.

Michael Myers
  • 188,989
  • 46
  • 291
  • 292
  • 5
    "To prevent confusion, I often mark my method parameters final, which keeps them from being reassigned (accidentally or not) inside the method." I don't believe you, why would you change every single function to make explicit an already existent language feature? Why I ask this is because, one can't really understand Java if it isn't obvious to him that assignment doesn't modify the object. – L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ Mar 26 '10 at 22:39
  • 1
    @Longpoke: I am not the only one who reads my code, so whether or not *I* understand it isn't really relevant. And I didn't say I changed every single function -- although if you use PMD, which I do, it will warn you every time you don't mark a parameter final. – Michael Myers Mar 27 '10 at 03:28
  • 1
    It's starting to bug me that all variables aren't final by default in Java. @Longpoke--the more restrictive you can be by habit, the less chance of errors. Why would you not want to prevent potential errors whenever possible--even at the "cost" of more explicit code such as creating a new variable instead of re-assigning a parameter? (I personally don't consider more explicit code a cost in most cases, hence the quotes) – Bill K Apr 27 '10 at 18:15
  • 5
    @Bill K: Marking parameters as final is okay, if you want to prevent treating the argument as a local variable. But it doesn't make sense to me to mark it final only to "prevent" people from thinking that local argument assignment modifies the outer reference; if they thought that in the first place they probably should go learn Java (or almost any popular OO language?) first. Also, I agree with being restrictive in Java since it sort of goes with the philosophy of static typing, I think I'll mark my parameters final for now on :) – L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ Apr 27 '10 at 20:17
  • @Longpoke - I think that the real point of confusion is when someone reading the method expects the parameter's value to be the same as when the method call started ... and fails to notice the intervening assignment. – Stephen C Nov 24 '11 at 13:04
33

Java passes references by value, so you get a copy of the reference, but the referenced object is the same. Hence this method does modify the input list.

Rytmis
  • 31,467
  • 8
  • 60
  • 69
8

The references themselves are passed by value.

From Java How to Program, 4th Edition by Deitel & Deitel: (pg. 329)

Unlike other languages, Java does not allow the programmer to choose whether to pass each argument by value or by reference. Primitive data type variables are always passed by value. Objects are not passed to methods; rather, references to objects are passed to methods. The references themselves are passed by value—a copy of a reference is passed to a method. When a method receives a reference to an object, the method can manipulate the object directly.

Used this book when learning Java in college. Brilliant reference.

Here's a good article explaining it. http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html

the_new_mr
  • 3,476
  • 5
  • 42
  • 57
  • Excellent description. The most concise and helpful I've read about the subject. – JD Gamboa Nov 02 '19 at 01:16
  • What is the difference between typical passed by reference and reference passed by value? Is there any advantages of doing it or it is just the way Java was design? – Bitwise DEVS May 18 '22 at 15:09
  • If you pass-by-reference in C++, manipulations on the *reference* actually affect the object that was passed into it. Whereas in Java, even if you assign the reference received as a parameter to the method to a new object, the original object is unchanged because you only received a copy of the reference as a parameter. Take a look at this article (I haven't read the whole thing but the bit about litmus test will interest you): https://www.javadude.com/articles/passbyvalue.htm – the_new_mr May 19 '22 at 03:53
2

Well, it can manipulate the ArrayList - which is an object... if you are passing an object reference around (even passed by value), changes to that object will be reflected to the caller. Is that the question?

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
1

I think you are confused because vsName is modified. But in this context, it is just a local variable, at the exact same level as shortenedVoiceSetName.

PhiLho
  • 40,535
  • 6
  • 96
  • 134
-4

It's not clear to me what the exact question within the code is. Java is pass-by-value, but arrays are pass-by-reference as they pass no object but only pointers! Arrays consist of pointers, not real objects. This makes them very fast, but also makes them dangerous to handle. To solve this, you need to clone them to get a copy, and even then it will only clone the first dimension of the array.

For more details see my answer here: In Java, what is a shallow copy? (also see my other answers)

By the way, there are some advantages as arrays are only pointers: you can (ab)use them as synchronized objects!

Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
mark
  • 84
  • 1
  • 2