4

I came across the interesting topic about final method parameters and that they essentially don't provide much advantages. I wondered if it would be sensible to mark only those method parameters as final, when it is advisable to pass an immutable object.

I don't know if this might mislead some people when they're reading the code, because final does not provide this immutability, and even the compiler wouldn't understand that I would like an immutable object to be passed to this method param. But it would be sth like a "human-readable" indicator (especially in APIs) that passing an immutable object is advised.

How would such a concept be evaluated by experienced java programmers?

closed as primarily opinion-based by Neil, amon, GlenH7, user40980, user22815 Jul 2 '15 at 11:27

Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 4
    Could be useful styling practice within a small team, but this is hardly practical on a larger scale. I personally would much rather prefer javadoc explicitly stating as such since I'll take clear and verbose over unclear and compact anyday. – Neil Jul 1 '15 at 11:19
  • 1
    What situation are you encountering where the type you are receiving may be mutable or immutable? – user40980 Jul 1 '15 at 12:57
  • I think anyone that understands what Java final means (as opposed to e.g. C++'s const-ness) would not be mislead by this. The only benefit is it prevents one from reassigning reference parameters inside the method, which may indicate there is a logic error somewhere. – user22815 Jul 2 '15 at 11:26
4

Personally, I used to use final always (these days, from-time-to-time) only to ensure variables are not being re-assigned; nothing more, nothing less.

The advantage of not reassigning variables is important to me actually, as it discourages the 'crutch' of temporary variables. This in turn encourages me to re-inspect my code for repetitive code (replacing them with inlined methods, or even to re-structure them) and eliminates potential bugs due to careless re-assignments.

The latter is more helpful in long do-it-all methods, but once broken down into smaller methods, it's easier to see the scope of variables and therefore also to less likely to re-assign them in the first place. Hence my personal preference to use them lesser now.

To address your concern about accepting mutable/immutable objects, my suggestion is to make one the default approach for your library/codebase, stick with that and then document the exception. In other words, if it's better code-wise to be passing immutable objects by default, then you can make that clear so from 'Getting Started'-kind of documentation to address this codebase-wide. You can then make use of @assylias's suggestion to document the methods to say something like:

/**
 *  This method works with mutable arguments as well.
 */

Or

/**
 *  The side-effect of this method modifies the mutable arguments.
 */

You can also play with your classes name by calling them MyImmutableType (for example). I generally avoid this as their names don't 'roll well', but YMMV.

// this has to return a new MyImmutableType instance
public MyImmutableType doSomething(MyImmutableType input);

// this possibly mutates the mutable argument, which the caller will then use
public void doSomething(MyMutableType input);

Perhaps more importantly, final your arguments' classes too so that if callers/users of your codebase decide to check your source code, then can also immediately tell that the class is immutable.

public final class Wrapper<T> {
    private final int id;
    private final T payload;

    public Wrapper(int id, T payload) {
        this.id = id;
        this.payload = payload;
    }
}

In conclusion, if I see a final keyword in the method signature, all I know is that the developer is doing something right by not (potentially) reassigning method arguments within the method. It should not be relied upon to indicate whether arguments should/must be be immutable.

1

I don't think it is a good idea:

  • using final for a method parameter, as you noticed, does not give any immutability guarantees
  • I personally find that it clutters the code unnecessarily
  • People using your code should not have to read your code! final is not part of the method contract / its javadoc so it is not the right medium to convey information to the callers.

I would rather indicate in the javadoc the assumptions made by the method:

/**
 *  This method expects its argument to be immutable
 */

ps: I'm not sure why you want to receive an immutable object though as it makes no difference for the code in your method (unless you spawn new threads etc.)...

Not the answer you're looking for? Browse other questions tagged or ask your own question.