6

So do I need to repeat final in the case below ?

interface Foo {

    void meth(final Bar bar);
}

public Baz implements Foo {

    @Override
    void meth(/* is it final ?*/ Bar bar){}
}

The question is not only for interface inheritance but class inheritance also - I guess the answer will be the same

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
  • 3
    Any reason you couldn't just hit compile and see for yourself? – Ant P Dec 01 '13 at 22:08
  • @AntP: I think it's an interesting question – Mr_and_Mrs_D Dec 01 '13 at 22:09
  • @AntP: and not only because if this is not the case I'd like to know why – Mr_and_Mrs_D Dec 01 '13 at 22:10
  • 4
    `final` is not part of the method signature. It is redundant in your interface definition. – Oliver Charlesworth Dec 01 '13 at 22:10
  • 1
    Read the definition of [*signature*](http://docs.oracle.com/javase/tutorial/java/javaOO/methods.html) in Java - it is based on the method name and parameters type, nothing else. – Nir Alfasi Dec 01 '13 at 22:11
  • @Oli you are correct but that is a parameter not a final data member of the interface. @Mr&Mrs : I too think this is an important question. I think it must be put that way. i.e. final should be put as a parameter when over riding it. – Sameer Sawla Dec 01 '13 at 22:13
  • 2
    @SameerSawla: Yes, that's why I said "`final` is not part of the **method** signature" ;) – Oliver Charlesworth Dec 01 '13 at 22:14
  • @OliCharlesworth: Thanks - is it really wrong to have it there then - or would it make sense to have it there to declare intended use (an out parameter for instance) ? You may post an answer – Mr_and_Mrs_D Dec 01 '13 at 22:26
  • 1
    @Mr_and_Mrs_D: It's wrong in the sense that it doesn't do anything. It can't even prevent something being an "out" parameter. – Oliver Charlesworth Dec 01 '13 at 22:29
  • @OliCharlesworth: yes I got this - do you think that final in this case might "serve as some kind of documentation" ? – Mr_and_Mrs_D Dec 01 '13 at 22:37
  • 2
    @Mr_and_Mrs_D: But it doesn't document anything... ;) `final` is an internal implementation detail. – Oliver Charlesworth Dec 01 '13 at 22:41
  • @Mr_and_Mrs_D when you read the answer in the link - read till the end: the "documentation" part refers to class members that were declared final, not to method arguments. – Nir Alfasi Dec 01 '13 at 22:43
  • @alfasin: I took it from the answer below - stay calm please :) – Mr_and_Mrs_D Dec 01 '13 at 22:45
  • @Mr_and_Mrs_D the answer below copied it from the answer in the [*link*](http://stackoverflow.com/questions/5380177/final-arguments-in-interface-methods-whats-the-point) (suspected duplicated). Sorry if you got offended - didn't mean to. – Nir Alfasi Dec 01 '13 at 22:48
  • @EJP saying that one should declare a method argument as final in an interface shows misunderstanding of `final`. If you want to convince me with anything you should reason with me - not "shout orders"... – Nir Alfasi Dec 02 '13 at 00:12

1 Answers1

8

Yes you do need to redeclare method parameters as final if you want the compiler to make sure these parameters are never reassigned in the current method. This holds both when overriding interface and class definitions.

The reason for this is rather simple: This is the behavior specified in the Java language specification. However, the compiler could not even check for not reassigning final parameters even if it wanted to:

The final modifier for variables in method scope is actually not translated into byte code or written elsewhere into the Java class file format. It basically disappears after the compilation of a specific class or interface and cannot be traced after this compilation. Since each class and interface is compiled independently of other classes and interfaces, the compiler or the JVM run time verifier could not make sure that final parameters were assigned with a new value in subclasses or interface implementations. It is only within the compilation of a single class where the Java compiler can assure that such assignments do not occure. The declaration of final parameters is therefore local for a class and it would not be possibility to change this behavior in the future or to find out about this feature by using run time reflection.

Using a final parameter in an abstract method signature does therefore not serve a purpose, neither a real one or a documentary one: Since Java implements method calls by call by value and not by reference, the final modifier will never effect code outside of the implementing method's scope. If a method parameter variable is reassigned is therefore merely a detail of the methods actual implementation. I would therefore personally never use it for defining abstract methods in classes or interfaces. It is allowed but meaningless.

Within non-abstract method definitions, declaring a method variable final only serves one of two purposes:

  • You want to use a variable inside an anonymous class's scope.
  • You want the compiler to check that you did not accidentaly reassign a variable. This is escpecially useful when dealing with many variables of similar type. Here, the final modifier also serves as some kind of documentation.

UPDATE: Since Java 8, a method parameter is attributed on if it is synthetic (non represented in the source code, mandated (implicitly present in the source code, e.g. the this reference for lambda expressions) or if it is final. This does however not effect overridden methods where the final declaration needs to be repeated for this flag to be set. Furthermore does the Java language not pay attention to these flags, it is only meta frameworks that read these flags to implement their logic which might react to theses flags.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • -1 "Yes you do have to declare it again. For both interface and class definitions." - not true for interface! see Oli Charlesworth's first comment. It has nothing to do with compile-time information. – Nir Alfasi Dec 01 '13 at 22:16
  • Well, the comment misses the point. A method or parameter annotation is neither part of a method's signature. It is still possible to preserve such information when overriding a method. You might want to read the Java language specification. – Rafael Winterhalter Dec 01 '13 at 22:21
  • 2
    @alfasin: I think "have to" in the sense that the `final` in the interface has no bearing on the implementation (because it's redundant), so if you want the compiler to enforce immutability on the implementation, you'll need `final` there too. – Oliver Charlesworth Dec 01 '13 at 22:21
  • 1
    @OliCharlesworth exactly, that's why the developer "have to" use the `final` keyword with any *implementation* (class) - not with interface. This answer is full of errors: 1. "subclass" is a term that one uses for inheritance - not for interface implementation. 2. This has nothing to do with bytecode and with compile-time information. 3. inner-classes has nothing to do with it. Etc. All it has to do with, is the definition in JLS which ironically enough raphw directed me to read after I already supplied the link... – Nir Alfasi Dec 01 '13 at 22:37
  • 1. Ok, got me. Make this subclasses **or interface implementations**. Done. 2. This has to some extend to do do with the resulting byte code, I tried to explain why it would not be possible by the compiler to enfore the requested behavior when overriding methods with `final` parameters. Should I instead just answer *no, not possible*? The JLS does not specify some sort of attribute for a method declaration, but you could of course write your own Java compiler that enforces the requested behavior by writing some additional data to the class file. 3. You did not read my answer. – Rafael Winterhalter Dec 01 '13 at 22:46
  • 2
    There is no other answer for this question. So where did I copy an answer here? And even if, would it not be great if I provided an answer as complete as possible even if I had taken this from somewhere else? When you are done with the JLS, you might read up some information about stack overflow. I will carry this first ever down vote on stack overflow with pride. – Rafael Winterhalter Dec 01 '13 at 22:49
  • @raphw when you write a **wrong** answer - you should expect downvotes (nothing to be ashamed of - but also nothing to be proud of). Happened to me many times if it makes you feel better. You wrote a few wrong things in your answer- for example it has nothing to do with bytecode. – Nir Alfasi Dec 01 '13 at 22:59
  • As for writing your own compiler - of course you can do that but if your compiler won't work according to JLS - it will not be a Java compiler. The JLS is very clear about the definition of a method signature. That's the only reason why it won't work. About the "documentation" part - you probably read somewhere that declaring a **class member** as final also serves as documentation that this member should not be overridden. It has nothing to do with declaring a method argument as final. – Nir Alfasi Dec 01 '13 at 23:00
  • Same thing goes for anonymous inner class - it can't modify a member of the parent class, and, until Java 8 it must explicitly be declared final in order to use it. Again, it has nothing to do with our case. – Nir Alfasi Dec 01 '13 at 23:02
  • I feel like this discussion became a little bit too heated and I want to end it now. I tried to give an answer which went a little bit beyond *the JLS does not say so* and explained why the compiler cannot emforce this modifier. The answer you linked is kind of brief, I like mine better and I still disagree with you about it being wrong even though I understand why you think it is. Let's call it a day. – Rafael Winterhalter Dec 01 '13 at 23:08
  • Funny that people feel the discussion has been heated, it's not. And if you'll fix your answer - not only I'll remove the downvote - I'll upvote it too. I mistakenly thought that you took the "documentation" part from the answer in the "suspected duplicate" thread - sorry for that. But it wasn't the point. The point is that you wrote a few mistakes that might confuse future SO members - when they'll see this answer marked as "approved" they might think everything you wrote is correct. – Nir Alfasi Dec 01 '13 at 23:46
  • @alfasin: I do think you should remove this downvote - this is a good answer ;) – Mr_and_Mrs_D Jun 13 '15 at 21:00