views:

267

answers:

8

Eclipse has an option to warn on assignment to a method's parameter (inside the method), as in:

public void doFoo(int a){
   if (a<0){
      a=0; // this will generate a warning
   }
   // do stuff
}

Normally I try to activate (and heed) almost all available compiler warnings, but in this case I'm not really sure whether it's worth it.

I see legitimate cases for changing a parameter in a method (e.g.: Allowing a parameter to be "unset" (e.g. null) and automatically substituting a default value), but few situations where it would cause problems, except that it might be a bit confusing to reassign a parameter in the middle of the method.

Do you use such warnings? Why / why not?

Note:

Avoiding this warning is of course equivalent to making the method parameter final (only then it's a compiler error :-)). So this question http://stackoverflow.com/questions/500508/why-should-i-use-the-keyword-final-on-a-method-parameter-in-java might be related.

+2  A: 

For me, as long as you do it early and clearly, it's fine. As you say, doing it buried deep in four conditionals half-way into a 30-line function is less than ideal.

You also obviously have to be careful when doing this with object references, since calling methods on the object you were given may change its state and communicate information back to the caller, but of course if you've subbed in your own placeholder, that information is not communicated.

The flip side is that declaring a new variable and assigning the argument (or a default if argument needs defaulting) to it may well be clearer, and will almost certainly not be less efficient -- any decent compiler (whether the primary compiler or a JIT) will optimize it out when feasible.

T.J. Crowder
It is not clear to me how reassigning an object reference, is going to make the object (that you no longer have a reference to) communicate information back to the caller. Could you please explain that to me?
OscarMk
@OscarMk: My point was exactly that: It won't. :-) So (say) you receive the argument `obj`, and near the top of the function you assign a new reference to it if a certain condition exists. Near the bottom of the function you call `obj.foo()`. If you've assigned a new reference to `obj`, then obviously the caller's object won't receive the `foo` call, your replacement will -- but it's not obvious looking at the code at the end there that that will happen.
T.J. Crowder
@T.J Crowder: Yes that is what I though, thank you.
OscarMk
+1  A: 

Different compiler warnings can be appropriate for different situations. Sure, some are applicable to most or all situations, but this does not seem to be one of them.

I would think of this particular warning as the compiler giving you the option to be warned about a method parameter being reassigned when you need it, rather than a rule that method parameters should not be reassigned. Your example constitutes a perfectly valid case for it.

danben
+6  A: 

The confusing-part is the reason for the warning. If you reassign a parameter a new value in the method (probably conditional), then it is not clear, what a is. That's why it is seen as good style, to leave method-params unchanged.

Mnementh
I agree that it is quite confusing. In general, if you're passing in a param, you should use that param, not reassign it to something else.
Jeff Storey
I don't agree - inputs often need to be sanitized.
danben
Sanitize it into a new local variable.
Mnementh
@Mnementh, if you create a new local variable for the purpose it can be tricky to pick appropriate names for all the similar variables.
finnw
@finnw: That's actually the biggest reason I frequently "break" the rule on this. I'm just not inventive enough. :-)
T.J. Crowder
@finnw/Crowder: ...and because of my lack of imagination, I personally am very fond of the semantic/pragmatic Hungarian prefix notation, enabling us to use the same name for object member variables (e.g. the "m_" wart), method parameters and local variables (e.g. "the..."). Not that I've managed to be consistent about it!
Pontus Gagge
+4  A: 

Assigning a method parameter is not something most people expect to happen in most methods. Since we read the code with the assumption that parameter values are fixed, an assignment is usually considered poor practice, if only by convention and the principle of least astonishment.

There are always alternatives to assigning method parameters: usually a local temporary copy is just fine. But generally, if you find you need to control the logic of your function through parameter reassignment, it could benefit from refactoring into smaller methods.

Pontus Gagge
*"Assigning a method parameter is not something most people expect to happen..."* I'll dispute that as a universal statement. In fact, I'd say in *functional* languages and similar (including JavaScript), it's darned near the norm. In my experience, it's less common in Java and C++, and neither common nor uncommon in C. Why that should be I don't know, but it may have something to do with the approaches people take to problem solving in different languages and environments.
T.J. Crowder
Nitpicking: in a **functional** language, assignment does not happen, only new bindings, much as imperative languages declare a new temporary variable. Actually, I would suggest that what you describe is **one** of the reasons JavaScript has a poor reputation, even though its design as a prototype based OO language is actually pretty nifty. It was once said of the Amiga that it was much better than its fanboys...
Pontus Gagge
A: 

I sometimes use it in situations like these:

void countdown(int n)
{
   for (; n > 0; n--) {
      // do something
   }
}

to avoid introducing a variable i in the for loop. Typically I only use these kind of 'tricks' in very short functions.

Personally I very much dislike 'correcting' parameters inside a function this way. I prefer to catch these by asserts and make sure that the contract is right.

Maurits Rijk
Sorry, but I think your example is the perfect case *for* this warning. I find it needlessly complicated. E.g., what if the function later grows (as functions always do), and you try to use n to, say print "Iteration <x> out of <n>"?
sleske
A: 

I usually don't need to assign new values to method parameters.

As to best-practices - the warning also avoids confusion when facing code like:

       public void foo() {
           int a = 1;
           bar(a);
           System.out.println(a);
       }

       public void bar(int a) {
           a++;
       }
rflexor
+2  A: 

Reassigning to the method parameter variable is usually a mistake if the parameter is a reference type.

Consider the following code:

MyObject myObject = new myObject();
myObject.Foo = "foo";
doFoo(myObject);

// what's the value of myObject.Foo here?

public void doFoo(MyObject myFoo){   
   myFoo = new MyObject("Bar");
}

Many people will expect that at after the call to doFoo, myObject.Foo will equal "Bar". Of course, it won't - because Java is not pass by reference, but pass by reference value - that is to say, a copy of the reference is passed to the method. Reassigning to that copy only has an effect in the local scope, and not at the callsite. This is one of the most commonly misunderstood concepts.

Winston Smith
Actually, Java methods are only call-by-value. Nevertheless, I don't think this has much to do with the question.
danben
@dan I think it's relevant. *Is it problematic to assign a new value to a method parameter?" - yes, it can be, because it may not do what someone expects.
Winston Smith
Right, but in this particular case you are referring to someone who does not understand how the language works. Compiler warnings are not going to protect against that.
danben
A: 

You shoud write code with no side effect : every method shoud be a function that doesn't change . Otherwise it's a command and it can be dangerous.

See definitions for command and function on the DDD website :

Function : An operation that computes and returns a result without observable side effects.

Command : An operation that effects some change to the system (for example, setting a variable). An operation that intentionally creates a side effect.

Jean-Philippe Caruana
@Jean-Philippe: (I don't consider modifying method parameter good practice) The question is not about side effects. Actually changing a primitive parameter in Java as exactly zero side-effect seen that Java is "pass by value". You're introducing the concept of referential transparency and pure functions, which may be entertaining in the functional programming world. But here we're talking about Java and you'll find that in Java a *lot* of Java method actually are not referentially transparent. The original question is not about "setting a variable", it's about modifying a method parameter.
Webinator