Java is NEVER pass-by-reference, right?...right?

22,735

Solution 1

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.

Solution 2

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.

Solution 3

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

Solution 4

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?

Solution 5

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.

Share:
22,735
Troy Nichols
Author by

Troy Nichols

Programmer.

Updated on July 09, 2022

Comments

  • Troy Nichols
    Troy Nichols almost 2 years

    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?

  • DJClayworth
    DJClayworth about 15 years
    The 2 principles of Java variables: 1) variables are passed by value 2) all variables are references (or primitives).
  • L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
    L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ about 14 years
    "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.
  • palantus
    palantus about 14 years
    @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.
  • Bill K
    Bill K about 14 years
    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)
  • L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
    L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ about 14 years
    @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 :)
  • Stephen C
    Stephen C over 12 years
    @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.
  • JD Gamboa
    JD Gamboa over 4 years
    Excellent description. The most concise and helpful I've read about the subject.
  • Nico Wawrzyniak
    Nico Wawrzyniak over 2 years
    Java is strictly pass-by-value, even for Arrays! javadude.com/articles/passbyvalue.htm
  • Sam Ginrich
    Sam Ginrich over 2 years
    and Java indeed is about the behavior of Objects!
  • Sam Ginrich
    Sam Ginrich over 2 years
    There are also arrays of non-object types.
  • Sam Ginrich
    Sam Ginrich over 2 years
    @Nico Wawrzyniak Pasting that phrase often enough doesn't make it true.
  • Nico Wawrzyniak
    Nico Wawrzyniak over 2 years
    @Sam Grinrich Correct, but understandig the linked article does.
  • Nico Wawrzyniak
    Nico Wawrzyniak over 2 years
    If you prefer an official source you can read it up in the Java documentation by Oracle, but I find it more difficult to understand compared to the javadude article: docs.oracle.com/javase/specs/jls/se11/html/jls-8.html#jls-8.‌​4.1 and docs.oracle.com/javase/specs/jls/se11/html/…
  • Sam Ginrich
    Sam Ginrich over 2 years
    @Nico Wawrzyniak pasted +1 time :(
  • Nico Wawrzyniak
    Nico Wawrzyniak over 2 years
    Okay, so you're resistant to facts. It won't get any more official and correct than the Java documentation by Oracle. In case you did not know: These are the guys who define the Java language.
  • Sam Ginrich
    Sam Ginrich over 2 years
    Oracle is a fact, Java passes Objects by Reference is another one. "Java is pass by value" is famous nonsense
  • Bitwise DEVS
    Bitwise DEVS almost 2 years
    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?
  • the_new_mr
    the_new_mr almost 2 years
    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): javadude.com/articles/passbyvalue.htm