JDK-8166422 : Javac does not allow private interface methods to be declared final
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Priority: P4
  • Status: Resolved
  • Resolution: Won't Fix
  • OS: generic
  • CPU: generic
  • Submitted: 2016-09-20
  • Updated: 2016-10-04
  • Resolved: 2016-10-04
Related Reports
Relates :  
Description
This program:

// -- 
interface IfaceWithPrivateFinalMethod {
    private final void privateFinalMethod() {}
}

triggers the error:

X.java:2: error: modifier final not allowed here
    private final void privateFinalMethod() {}
                       ^
1 error

It would seem since private methods are not inherited, they are final anyway and the compiler should allow the combination of private and final to modify an interface method.
Comments
I have no objection to closing. I think our handling of finality at the source, classfile (flags), and VM level is somewhat inconsistent and ad-hoc, but so be it. The VM certainly does not deal with private methods (class or interface) in an optimal way, but we will look at that for 10. The current class method behaviour seems to be tied in with an ancient classfile compatibility issue from the "classic VM" days (1.1?) but I don't know what that means.
04-10-2016

@David, I will wait for the end of business week before closing, unless you concur and have no objections already - The recommendation "If there are potential optimizations that rely on a method never being overridden, those optimizations should be smart enough to know that this is always true for static and private methods, regardless of their flags. It should perhaps also be smart enough to identify "never overridden" methods in other circumstances." seems simple enough ???
03-10-2016

Responding to the language feature: I don't see any benefit to allowing 'final' on private and static interface methods. It doesn't really express anything useful currently when applied to 'private'/'static' class methods (the invocation mode will never be 'virtual' (15.12.3, 15.12.4.4), so the question of whether the method can be overridden or not is irrelevant). And it suggests to users that they can use 'final' on regular instance methods of interfaces ("default"-like methods), leading to disappointment when they discover this is not true. Our consistent story is: 'final' is available as a modifier on class methods, not interface methods. Responding to the JVM discussion: ACC_FINAL is prohibited on interface methods (4.6), and I see no reason to change that. It doesn't communicate anything to anyone that isn't already understood. If there are potential optimizations that rely on a method never being overridden, those optimizations should be smart enough to know that this is always true for static and private methods, regardless of their flags. It should perhaps also be smart enough to identify "never overridden" methods in other circumstances. JDK-8160200 is about the flags of the InnerClasses attribute, and merely acknowledges that some source languages may not require an explicit "final" in order claim that a class is, in fact, final. The table for method flags (4.6) does not bother to make this distinction, which is fine -- explicit and implicit declarations are both "declared". But the observation in JLS 8.4.3.3 that some methods "behave as if they are final" is not a claim that those methods actually *are* final, nor is it meant to influence the generated class files. (To make such a change would be a major problem for serialization, since UIDs depend on the values of these class file flags.)
03-10-2016

Yes this is a spec question. And yes the VM would need updating as it checks allowed modifiers.
21-09-2016

Please see that the proposed edits to JLS in JDK-8072872 do not call out final as one of the InterfaceMethodModifiers. If it is amended to include final, it would also help to have it stated whether final + static combination is allowed (as is with a class method). I'll prepare a patch, but will wait for an express nod from Alex/Dan as they are in charge of the specification. This will also need coordination with hotspot since the VM likes final neither on static nor private interface methods as of now and throws a java.lang.ClassFormatError:
21-09-2016

Sorry, thought you were suggesting that being implicitly final was sufficient. Thanks.
21-09-2016

"There still seems no reason to disallow "private final" for interface methods. " @David, By citing 8.4.3.3, I am agreeing with you.
21-09-2016

There still seems no reason to disallow "private final" for interface methods. There is also the question of whether private methods and methods in a final class should have the ACC_FINAL bit set (ref JDK-8160200). The reason this arose is that the VM only considers a method to be final if the ACC_FINAL bit is set. There would seem to be some optimization opportunities if implicitly final methods were also treated as "final" - either by the VM being aware of the implicitly final rules, or else having the compiler set ACC_FINAL on implicitly final methods.
21-09-2016

8.4.3.3 final Methods: A private method and all methods declared immediately within a final class (��8.1.1.2) behave as if they are final, since it is impossible to override them. // ----- The existing reasoning/wording in JLS8 at a time when private methods in interfaces are illegal is neutral enough to apply, it would seem.
20-09-2016