views:

1510

answers:

5

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?

+18  A: 

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
The 2 principles of Java variables: 1) variables are passed by value 2) all variables are references (or primitives).
DJClayworth
+1  A: 

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
+33  A: 

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
Thanks for the example.
Troy Nichols
"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.
Longpoke
@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
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
@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 :)
Longpoke
A: 

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
+11  A: 

See my article, "Java is Pass-by-Value Dammit!"

http://javadude.com/articles/passbyvalue.htm

Scott Stanchfield
Excellent article.
Don Branson
+1 from me - very nice indeed, especially the bit about RMI. That's often forgotten.
duffymo