3

I read with interest this question : Can I pass parameters by reference in Java?

What comes out it is that parameters (which are not primitives) are passed by copying the reference value. And so as the example states; you can't modify the reference of the parameter you gave:

Object o = "Hello";
mutate(o)
System.out.println(o); // Will print Hello

private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!

This kind of problem could be avoided using finallike this :

private void mutate(final Object o) { o = "Goodbye"; } //Compilation error

The questions :

  • Is the final keyword in such a case only used to throw a compilation error ?
  • If in the end you can't modify the reference of the given parameter why isn't final implicit or mandatory ?

I rarely used final for method parameters in Java but now I can't think of any case where you would voluntarily omit to put final to a method parameter.

Thanks!

Community
  • 1
  • 1
Michael Laffargue
  • 10,116
  • 6
  • 42
  • 76
  • you avoid the use of that parameter as a variable inside the method, letting it simple to read / understand – Francisco Spaeth Jul 31 '12 at 09:02
  • 1
    When you create anonymous inner-class inside a method, you need to make the parameter as `final` in order to use it inside that anonymous class. – Eng.Fouad Jul 31 '12 at 09:03

5 Answers5

4

I usually do this to prevent accidental or unintended modifications of this reference. e.g.

private String doSomething(final String arg) {
   // final to prevent me doing something stupid!
}

One interesting scenario is in setters. You want to ensure that you set the member variable and not the arg passed in. e.g.

public void setArg(String arg) {
   _arg = arg;
}

In the above scenario, if the method parameter is not final, then I could possibly set

   arg = arg;

by mistake. The above is a common typo, or can occur due to search/replace refactoring. By making arg final, you can't accidentally reassign it.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
4

To avoid this:

public void searchBiggest(String startingWith) {
    for (String s : collection) {
        if (s.startsWith(startingWith)) {
            startingWith = s;
        }
    }
    return startingWith;
}

As you can see it makes the code not intuitive because the parameter could be holding a different value that the one passed.

From Hard Core Java - Chapter 2:

Little bugs like this are often the most difficult to locate. By Murphy’s Law, you can absolutely guarantee that this code will be in the middle of a huge piece of your project, and the error reports won’t directly lead you here. What’s more, you proba- bly won’t notice the impact of the bug until it goes into production and users are screaming for a fix.

You cannot afford to forget that once you write code, the story is not over. People will make changes, additions, and errors in your code. You will have to look through the code and fix everything that was messed up. To prevent this problem from occur- ring, do the following:

and a similar sample is done using the parameter, and additionally invoking other methods with the parameter (already changed).

Francisco Spaeth
  • 23,493
  • 7
  • 67
  • 106
3

Typically you shouldn't modify parameters as it can introduce hard to find bugs. However there are some useful idioms and situations where it can be useful:

public void print(String msg, int count) {
    msg = (msg != null)? msg : "Default";
    while(--count >= 0) {
        System.out.println(msg);
    }
}
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • Ok, so definitely it's just to avoid creating a new variable in some cases. Either you have confidence about the other developers and let it like that, either you force them to go with temp variable. – Michael Laffargue Jul 31 '12 at 09:11
  • Thanks everyone, I go with this answer as it's the closer to "Where not to use final?". Other answers gave me the benefits of `final` which I already knew. – Michael Laffargue Jul 31 '12 at 09:17
2

Java passes by value. So when you call mutate, a copy of o is passed.

Inside mutate, the copy of o is then set to point to "Goodbye". The original o is unchanged.

Setting the parameter to be final will not change this, but it will, as you've seen, stop reassignment of the copy of the original reference. Thats not the same, however, as stopping reassignment of the original reference.

pauljwilliams
  • 19,079
  • 3
  • 51
  • 79
2

1. You are passing the Object Reference Variable as the Argument, when you invoked the method by calling it.

    mutate(o);

2. By using the final keyword on the Parameter in the Method Definition, you have made it final, So it means that local Object Reference Variable o which is of type Object is final, so this variable can't be used to point any other object.

(Note: Its the Object Reference Variable which is final, Not the Object on the HEAP)

mutate(final Object o)

3. You can assign the object associated with the Object Reference Variable o to some other Object Reference Variable and then change it.

Object i = o;
 i = "GoodBye";
Kumar Vivek Mitra
  • 33,294
  • 6
  • 48
  • 75