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?

Unknown Id
  • 221
  • 2
  • 5
  • 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 01 '15 at 11:19
  • 1
    What situation are you encountering where the type you are receiving may be mutable or immutable? –  Jul 01 '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. –  Jul 02 '15 at 11:26

2 Answers2

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.

h.j.k.
  • 1,737
  • 1
  • 16
  • 20
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.)...

assylias
  • 1,187
  • 8
  • 20