Final arguments in interface methods - what's the point?

34,066

Solution 1

It doesn't seem like there's any point to it. According to the Java Language Specification 4.12.4:

Declaring a variable final can serve as useful documentation that its value will not change and can help avoid programming errors.

However, a final modifier on a method parameter is not mentioned in the rules for matching signatures of overridden methods, and it has no effect on the caller, only within the body of an implementation. Also, as noted by Robin in a comment, the final modifier on a method parameter has no effect on the generated byte code. (This is not true for other uses of final.)

Solution 2

Some IDEs will copy the signature of the abstract/interface method when inserting an implementing method in a sub class.

I don't believe it makes any difference to the compiler.

EDIT: While I believe this was true in the past, I don't think current IDEs do this any more.

Solution 3

Final annotations of method parameters are always only relevant to the method implementation never to the caller. Therefore, there is no real reason to use them in interface method signatures. Unless you want to follow the same consistent coding standard, which requires final method parameters, in all method signatures. Then it is nice to be able to do so.

Solution 4

Update: Original answer below was written without fully understanding the question, and therefore does not directly address the question :) Nevertheless, it must be informative for those looking to understand the general use of final keyword.

As for the question, I would like to quote my own comment from below.

I believe you're not forced to implement the finality of an argument to leave you free to decide whether it should be final or not in your own implementation.

But yes, it sounds rather odd that you can declare it final in the interface, but have it non-final in the implementation. It would have made more sense if either:

a. final keyword was not allowed for interface (abstract) method arguments (but you can use it in implementation), or
b. declaring an argument as final in interface would force it to be declared final in implementation (but not forced for non-finals).


I can think of two reasons why a method signature can have final parameters: Beans and Objects (Actually, they are both the same reason, but slightly different contexts.)

Objects:

public static void main(String[] args) {
    StringBuilder cookingPot = new StringBuilder("Water ");
    addVegetables(cookingPot);
    addChicken(cookingPot);
    System.out.println(cookingPot.toString());
    // ^--- OUTPUT IS: Water Carrot Broccoli Chicken ChickenBroth 
    //      We forgot to add cauliflower. It went into the wrong pot.
}

private static void addVegetables(StringBuilder cookingPot) {
    cookingPot.append("Carrot ");
    cookingPot.append("Broccoli ");
    cookingPot = new StringBuilder(cookingPot.toString());
    //   ^--- Assignment allowed...
    cookingPot.append("Cauliflower ");
}

private static void addChicken(final StringBuilder cookingPot) {
    cookingPot.append("Chicken ");
    //cookingPot = new StringBuilder(cookingPot.toString());
    //     ^---- COMPILATION ERROR! It is final.
    cookingPot.append("ChickenBroth ");
}

The final keyword ensured that we will not accidentally create a new local cooking pot by showing a compilation error when we attempted to do so. This ensured the chicken broth is added to our original cooking pot which the addChicken method got. Compare this to addVegetables where we lost the cauliflower because it added that to a new local cooking pot instead of the original pot it got.

Beans: It is the same concept as objects (as shown above). Beans are essentially Objects in Java. However, beans (JavaBeans) are used in various applications as a convenient way to store and pass around a defined collection of related data. Just as the addVegetables could mess up the cooking process by creating a new cooking pot StringBuilder and throwing it away with the cauliflower, it could also do the same with a cooking pot JavaBean.

Solution 5

I believe it may be a superfluous detail, as whether it's final or not is an implementation detail.

(Sort of like declaring methods/members in an interface as public.)

Share:
34,066

Related videos on Youtube

mindas
Author by

mindas

bean in the Java world

Updated on April 15, 2020

Comments

  • mindas
    mindas about 4 years

    In Java, it is perfectly legal to define final arguments in interface methods and do not obey that in the implementing class, e.g.:

    public interface Foo {
        public void foo(int bar, final int baz);
    }
    
    public class FooImpl implements Foo {
    
        @Override
        public void foo(final int bar, int baz) {
            ...
        }
    }
    

    In the above example, bar and baz has the opposite final definitions in the class VS the interface.

    In the same fashion, no final restrictions are enforced when one class method extends another, either abstract or not.

    While final has some practical value inside the class method body, is there any point specifying final for interface method parameters?

    • Paul Tomblin
      Paul Tomblin about 13 years
      final doesn't do anything with native types anyway, since they're copied.
    • Joachim Sauer
      Joachim Sauer about 13 years
      Just as a point of discussion: I just tried it and if two interface definitions vary only in the final attribute of an argument, then the resulting .class files are byte-for-byte identically (and of course javap -v produces the same output). The same is true for two classes that only differ in final on an attribute, by the way!
    • Joachim Sauer
      Joachim Sauer about 13 years
      @Paul: it does exactly the same thing as with reference types: it prevents the arguments itself to be modified (if used in the implementation).
    • Xairoo
      Xairoo about 13 years
      It has as much relevance as the public in the method signature.
    • Deepak
      Deepak about 13 years
      could anyone post a working example on this issue.?
    • Ted Hopp
      Ted Hopp about 13 years
      @Deepak - what's wrong with OP's code as an example? It seems perfectly clear.
    • Joachim Sauer
      Joachim Sauer about 13 years
      @Deepak: I see you asking for working examples on all kinds of questions, even when it doesn't seem to make a lot of sense. I think you should try learning some abstract thinking: try thinking about a problem without having some executable code in front of you. It will help you a lot in the long run.
  • mindas
    mindas about 13 years
    Valid point, although I don't think there were many IDEs when this feature was implemented (or left accidentally) :-)
  • Vishy
    Vishy about 13 years
    I think is in the category of static transient fields. ;)
  • Vishy
    Vishy about 13 years
    And public constructors on an abstract class.
  • mindas
    mindas about 13 years
    Does method parameter also qualify as a variable? It obviously is in practice, but is it in specification context?
  • Xairoo
    Xairoo about 13 years
    It can't be used to match signatures since it is does not appear in the actual .class file. It is for the compiler only.
  • Ted Hopp
    Ted Hopp about 13 years
    @mindas - the JLS says that there are seven kinds of variables. Method paramaters are fourth on the list.
  • Phil
    Phil over 10 years
    Ok. It's not really a correct answer to the question, (since I'm not forced to make my implementation of the interface method take final arguments, even if the interface says so), but it's still helpful, in that it's a nice explanation of why making method parameters final is a good idea to begin with.
  • ADTC
    ADTC over 10 years
    I believe you're not forced to implement the finality of an argument to leave you free to decide whether it should be final or not in your own implementation. But yes, it sounds rather odd that you can declare it final in the interface, but have it non-final in the implementation. It would have made more sense if either (a) final keyword was not allowed for interface (abstract) method arguments (but you can use it in implementation), or (b) declaring an argument as final in interface would force it to be declared final in implementation (but not forced for non-finals).
  • ADTC
    ADTC over 10 years
    "It's not really a correct answer to the question" You're right, I don't know what I was thinking... must have been the early wee hours of July or something. :)
  • Stefan Haberl
    Stefan Haberl over 8 years
    Documentation is next to useless, however, since the final modifier is not enforced on the implementing class. Your interface signature may simply lie.
  • Ted Hopp
    Ted Hopp almost 8 years
    The Java 8 language spec now says that there are eight kinds of variables (up from seven--they added lambda parameters). Method parameters are still fourth on the list (at least some things in life seem stable. :-)).
  • Dormouse
    Dormouse over 7 years
    IntelliJ does this. My version is IntelliJ IDEA 2016.1.3 Build #IU-145.1617.
  • The Godfather
    The Godfather over 5 years
    @Dormouse, it's interesting, because Android Studio (3.1.4 Build #AI-173.4907809) does not :(
  • Pavel_K
    Pavel_K over 5 years
    NetBeans doesn't.