7

Ok, so I understand why we should declare an argument to be final from this question, but I don't understand why we shouldn't...

Since Java always uses pass by value, this means that we can't return a new value through the given argument, we can only overwrite it, and make the argument useless therefore, because we don't use the passed value...

Is the only benefit of non-final method arguments in Java the fact that you don't have to make a local variable of the arguments' type?

P.S. This question was triggered by PMD's rule of MethodArgumentCouldBeFinal

Community
  • 1
  • 1
Vlad Ilie
  • 1,389
  • 1
  • 13
  • 37
  • You might substitute the passed value for an alternative object under certain circumstances. But yes it is rare – Richard Tingle Apr 25 '14 at 16:16
  • 7
    You don't always "make the parameter" (not argument) useless. For example, it's *reasonably* common to perform some input normalization, reusing the parameter: `text = StringUtil.nullToEmpty(text);` for example. – Jon Skeet Apr 25 '14 at 16:18
  • 2
    By the way, one of the points in the answer to the linked question, that you have to mark an argument `final` to use it in an anonymous inner class, is no longer true in Java 8. – ajb Apr 25 '14 at 16:20
  • 1
    I wouldn't make arguments final as it can make the code harder to read. If your method is too complicated for you to work out whether the arguments get changed, it is too complicated. Make your methods shorter and easier to understand and you shouldn't need to make your arguments or local variables final. You still have to make variables using an a nested class final, but this is a relatively rare case. – Peter Lawrey Apr 25 '14 at 16:24

4 Answers4

4

I can think of only 2 reasons not to make a parameter final:

  1. to save the use of a local variable if you need to overwrite the parameter's value in some edge cases (for instance to put a default if the param is null etc.). However, I wouldn't consider that a good practice in general.

  2. to save 6 characters per parameter, which improves readability.

Reason 2 is what leads me not to write it most of the time. If you assume that people follow the practice of never assigning a new value to a parameter, you can consider all parameters as implicitly final. Of course, the compiler won't prevent you from assigning a parameter, but I can live with that, given the gain in readability.

Joffrey
  • 32,348
  • 6
  • 68
  • 100
  • Re #2: is there an Eclipse setting to add `final` to all parameters by default? That would save a bit of typing. :) – ajb Apr 25 '14 at 16:23
  • 1
    @ajb There is an eclipse setting to insert them (when possible) in source "clean up", for sure. As for putting them by default on auto-generated code, I don't know. Anyway, I was rather talking about the visual result, not the typing of the word. – Joffrey Apr 25 '14 at 16:24
  • 3
    Java would be better if all variables were final by default and an extra word were needed to make them mutable – Display Name Apr 25 '14 at 16:31
  • @SargeBorsch Agreed, but I'd rather have only parameters be `final` by default (absence of keyword) and add a keyword `variable` or something to make them assignable. For local variables, I'd stick with the current state of the language. – Joffrey Apr 26 '14 at 08:14
1

It prevents you from making unintentional error in your code. Rule of thumb here is to make each field and each function argument you know you shouldn't change (I mean reference, you still can change value) in your code as final.

So basically its a mean to prevent programmer from shooting their foot. Nothing more.

Denis Kulagin
  • 8,472
  • 17
  • 60
  • 129
1

Whether you've to declare a local variable final or not (method parameter comes under this), is more of the requirement than a convention. You'll not get a certain answer saying you should always use final or you should never use final. Because that is really a personal preference.

I personally mark the parameters or local variables final when I really don't want their values to be changed, and it even shows my intention to other developers not to overwrite the values. But I don't do it for every parameters. Also for some, using final seems to be noise, as that really increases the code base.

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
1

Rule of thumb: Don't use it.

Final cannot stop you changing objects, only its reference, and this is because objects in java are, usually, not inmutable.

Take a look to this code:

class Example{
 // think about this class as a simple wrapper, a facade or an adapter
 SomeClass inner = new SomeClass();
 setInnet(Someclass inner){
   this.inner = inner;
 }
 // delegate methods.....
}

Now, in a method:

private void (final Example examp){

....

examp will be always the same object, but inner can vary... And inner is the important object here, the one which makes everything!

This may be an extreme example, and you may think that inner could be final but, if it's a utillery class, maybe it shouldn't. Also it's easy to find a more common example:

public void (final Map map){;
....
//funny things
....
//and then, in a line, someone does:
map.clear()
// no we have the same reference... but the object has change...
....

So, my point against final in arguments is that it's not guaranteed that all the code inside a final class is inmutable and so the final word can end lying you and mascarading a bug...

By putting final in params you can only show wishes, not facts, and for that you should use comments, not code. Moreover: it's a standar (de facto) in java that all arguments are only input arguments (99% of the code). Thus, final word in params is NOISE because it exists and means nothing.

And I don't like noise. So I try to avoid it.

I only use final word to mark the inner variables that will be used in an anonymous inner class (you can avoid marking it if they are effectively final, but it's cleaner and more readable).

UPDATED

final means 'assigned once' which in applied to method arguments means nothing in a program's logic nor in its design.

You can assign the arguments to a new object inside a method and outside there will not be any change.

The only difference putting final in arguments will be that you will not be able to assign that entities to another objects. Assigning arguments is something which may be ugly and something to avoid but its only a style problem and, at that point, the style problem should be the assignation itself and not the ausence of 'final' word.

I think that final is useless in arguments (and so, noise), but if someone is able to find a use of it I'll be happy to learn it. What can I achieve putting 'final' that cannot achieve without putting it?

inigoD
  • 1,681
  • 14
  • 26
  • So your reason against `final` is that you (or others) don't understand it's meaning (which can be a valid argument)? `final` neither means or implies immutable objects, so *"`final` word can end lying you"* is only true for someone who doesn't know what `final` means. *"mascarading a bug"* is quite unclear, because when the bug is that a method mutates an object, then this will happen for both `final` and non-`final` parameters. *"By putting `final` in params you can only show wishes, not facts"* This is wrong as well, because the parameter value is `final` and that's a fact. – Tom Jun 10 '16 at 10:54
  • @Tom before downvoting, please read the post linked in the question and you'll see which where the 2 reasons argued to use it and that I've talk about one of them... Anyway, I'll update the question explaining why, in my point of view, final word is only noise used in args according to its definition. – inigoD Jun 10 '16 at 11:55
  • You wrote that you think that `final` is noise, because it can lead to false assumptions about the immutability of the passed objects and that they won't be mutated in the method. The problem here is the developer, not `final`. `final` doesn't imply anything about the referenced object, it only restricts the variable itself (your update covers that). Since you're asking about an example: a quite common bugs on SO (for programming newbies I guess) is this `public MyBlubClass(String arg) { arg = arg; }`. As you can see, it should be `this.arg = arg`. A `final` for the parameter would detect that – Tom Jun 10 '16 at 13:17
  • If the `final` is missing, then neither your IDE nor the compiler will complain here. It may show a warning, but the IDE needs to be configured appropriately for that. You may also get a warning in software like Sonar, but this might not be used if you aren't a professional developer. So this bug might be missed for quite some time. And not an example, but also a reason for some developers: they prefer to have access on the originally passed argument. They also avoid reassigning the parameter variable due to that reason. But since this can intendedly happen, the compiler will then complain. – Tom Jun 10 '16 at 13:22