final keyword in method parameters

178,621

Solution 1

Java always makes a copy of parameters before sending them to methods. This means the final doesn't mean any difference for the calling code. This only means that inside the method the variables can not be reassigned.

Note that if you have a final object, you can still change the attributes of the object. This is because objects in Java really are pointers to objects. And only the pointer is copied (and will be final in your method), not the actual object.

Solution 2

There is a circumstance where you're required to declare it final --otherwise it will result in compile error--, namely passing them through into anonymous classes. Basic example:

public FileFilter createFileExtensionFilter(final String extension) {
    FileFilter fileFilter = new FileFilter() {
        public boolean accept(File pathname) {
            return pathname.getName().endsWith(extension);
        }
    };

    // What would happen when it's allowed to change extension here?
    // extension = "foo";

    return fileFilter;
}

Removing the final modifier would result in compile error, because it isn't guaranteed anymore that the value is a runtime constant. Changing the value from outside the anonymous class would namely cause the anonymous class instance to behave different after the moment of creation.

Solution 3

Java is only pass-by-value. (or better - pass-reference-by-value)

So the passed argument and the argument within the method are two different handlers pointing to the same object (value).

Therefore if you change the state of the object, it is reflected to every other variable that's referencing it. But if you re-assign a new object (value) to the argument, then other variables pointing to this object (value) do not get re-assigned.

Solution 4

The final keyword on a method parameter means absolutely nothing to the caller. It also means absolutely nothing to the running program, since its presence or absence doesn't change the bytecode. It only ensures that the compiler will complain if the parameter variable is reassigned within the method. That's all. But that's enough.

Some programmers (like me) think that's a very good thing and use final on almost every parameter. It makes it easier to understand a long or complex method (though one could argue that long and complex methods should be refactored.) It also shines a spotlight on method parameters that aren't marked with final.

Solution 5

Consider this implementation of foo():

public void foo(final String a) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            System.out.print(a);
        }
    }); 
}

Because the Runnable instance would outlive the method, this wouldn't compile without the final keyword -- final tells the compiler that it's safe to take a copy of the reference (to refer to it later). Thus, it's the reference that's considered final, not the value. In other words: As a caller, you can't mess anything up...

Share:
178,621

Related videos on Youtube

Aly
Author by

Aly

SOreadytohelp

Updated on February 26, 2021

Comments

  • Aly
    Aly over 3 years

    I often encounter methods which look like the following:

    public void foo(final String a, final int[] b, final Object1 c){
    }
    

    What happens if this method is called without passing it final parameters. i.e. an Object1 that is later changed (so is not declared as final) can be passed to this method just fine

    • Daniel Earwicker
      Daniel Earwicker over 14 years
      @Joachim - actually it's the same as const in C! The difference is that in Java a "pointer" to an object doesn't carry any special * syntax. Hence the confusion here. The variable is const/final, the object it points to is not.
    • Sean Owen
      Sean Owen over 14 years
      @Earwicker I think I take your point, but I think Joachim's is much more accurate in saying a 'final' method param has no implication for the caller, which is true, but not really what 'const' means in general.
    • Sean Owen
      Sean Owen over 14 years
      As an aside, I think you often see methods declared this way by people who believe, rightly, that it's clearer and less error-prone to not treat method params as local variables that can change. 'final' merely enforces this.
    • Joachim Sauer
      Joachim Sauer over 14 years
      @Earwicker: My C is weak. I thought I remembered that a const parameter forced every value that's passed in to come from a const variable as well. It seems that's wrong. Sorry.
    • Asaf
      Asaf over 14 years
      @Sean: i often see it, because our eclipse formatter is set up to do so. it's an artifact of a whole concept which promotes coding in the most restricted way (w.r.t access modifiers and in general), so when you remove the restriction you need to do so explicitly. my 2 cents.
    • Daniel Earwicker
      Daniel Earwicker over 14 years
      @Joachim - the issue is whether the variable is self-contained or is a reference/pointer to something else. This is always explicit in C, but depends on the type in Java. In C, you decide if a pointer variable should be const, or the object it points to, or both. You can put const in various places to get the combination you want. const Obj *p makes the Obj immutable but lets you change p to point to a different Obj, whereas Obj * const p leaves the Obj mutable and locks down p. Lastly const Obj * const p makes both the pointer and the object immutable.
    • scottb
      scottb almost 11 years
      @DanielEarwicker: I believe it is more correct to say that const in C is similar to final in Java, but the semantics of the two keywords are not identical between languages.
  • Thirler
    Thirler over 14 years
    It certainly makes a copy (there is an optimization where the compiler doesn't make a copy, when there is no difference with making a copy). However you have to keep in mind that in the case of an object. The object really only is a reference to an object. So in that case you will get a copy of the reference.
  • Mohammed Subhi Sheikh Quroush
    Mohammed Subhi Sheikh Quroush over 11 years
    if I have final int and thread inside my method can I still change the value of this int parameter from another methods ?
  • Armand
    Armand over 10 years
    It really is irrelevant if the parameter's value is a copy of the argument's source or the same reference. The fact of the matter is that any variable is just a reference to the actual object in memory. Marking a parameter as final prohibits the reassignment of the parameter within the code block of the function. However, if the parameter is not final, although one can reassign the parameter from the passed in argument to anything else, the caller of the function never loses its reference, and continues to point to the same object.
  • Armand
    Armand over 10 years
    You may wish to reconsider this position. Java does not pass by value. the simple test for this, is instead of passing String as the argument (which is immutable), pass in a StringBuffer() StringBuffer sb = new StringBuffer("Hello"); addWord(sb); System.out.println(sb.toString()); public void addWord(StringBuffer buf) { buf.append(" world"); } Running this, you will see sb outputs "Hello World". This would not be possible if it was pass by value, it is pass by reference, where the reference is a copy. Although arguably it is possible if it's final that the reference may not be copied
  • stuXnet
    stuXnet over 9 years
    @Armand Java is always (always!) pass-by-value.
  • huidube
    huidube about 9 years
    for future readers, pls read javadude.com/articles/passbyvalue.htm instead of these answers. Java is pass-by-value and key word 'final' just cares that this object wont be changed by accident within the method. (Or for the reason to be used in anonymous classes)
  • Erick G. Hagstrom
    Erick G. Hagstrom about 9 years
    That's a very good point. It addresses a slightly different point than I think the OP had in mind, as it's a special case of the requirement that variables in an enclosing scope that are referenced within an anonymous inner class must be final, but still it offers a good reason for at least some method parameters to be final.
  • Erick G. Hagstrom
    Erick G. Hagstrom about 9 years
    It's not "Because the Runnable instance would outlive the method", though. This is true of any anonymous inner class.
  • Erick G. Hagstrom
    Erick G. Hagstrom about 9 years
    Oh, and now in Java 8 we have the effectively final concept.
  • Darrell Teague
    Darrell Teague about 8 years
    Yes, Java passes-by-value and copies the object reference (which is a pointer to an object). The final keyword then prevents the reference from being changed but ... any mutable members of said object can still be modified, despite the fact that the parent reference is a copy. See: javaworld.com/article/2077424/learn-java/…
  • Mason
    Mason almost 8 years
    This answer does not address the topic which is "The final keyword".
  • Planky
    Planky about 7 years
    Java only copies the reference of the parameters, not the parameters themselves. This should be clarified in the answer.
  • Tom Taylor
    Tom Taylor almost 7 years
    What would be the effect of the change of the variable value (which is declared as final) on inner class ?
  • Tom Taylor
    Tom Taylor almost 7 years
    But still, public boolean doesStringStartsWithZero(String str) throws Exception { boolean result = str.startsWith("0"); str = "name"; } What's the difference between the above example (with inner anonymous class and this util method)?
  • Kareem Jeiroudi
    Kareem Jeiroudi over 3 years
    I happened to find this more like a convention in teams. There's really no right/wrong answer. However, I kinda agree to @Erick G. HagstromErick. Having final on methods parameters helps you understand the outgoings of the method at first glance, and draws some attention to those non-final parameters.
  • Dan Ortega
    Dan Ortega over 3 years
    Wow !! Please correct this ... object are passed by reference not by value, so objects pass a copy of the reference, not a new object .... Without this clarification this answer is very wrong.
  • Thirler
    Thirler over 3 years
    @DanOrtega I added some clarification