JDK-8072872 : 9.4: Allow interface methods to be 'private'
  • Type: Sub-task
  • Component: specification
  • Sub-Component: language
  • Affected Version: 7,8
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2015-02-10
  • Updated: 2018-08-03
  • Resolved: 2016-10-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
Overview of changes that have been identified:
- 9.4: Modify syntax, clarify that private methods are not "implicitly public" and are not "default".  Error checks for conflicts between 'private' and any of 'public', 'abstract', or 'default', similar to 8.4.3.
- 9.4.1: Private methods are not inherited or overridden in a subinterface.  (Inheritance definition actually works already, because it speaks of "abstract or default", but even without any spec change, this should definitely be tested.)
- 9.4.1.2: a private method can't override a public method.
- 8.4.8: Private methods are not inherited or overridden in a subclass.  (Again, no spec change, but should be tested.)
- 13.5.6: Describe the binary compatibility impact of changing the access of an interface method (similar to 13.4.7)

Need to investigate other potential impacts, where interface methods have been assumed to always be public (for example, in 6.6).
Comments
Alex, your comments have now been addressed in the above spec text.
11-10-2016

Suggested changes for misc other sections: ----- 6.6.1 [This is a very old bug -- since interfaces could have member classes, it has been possible for the "top level class" to be an interface.] Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class ***or interface*** (��7.6) that encloses the declaration of the member or constructor. ----- 8.4.8 A class does not inherit ***'private' or*** static methods from its superinterfaces. ----- 8.4.8.1 [Just cleanup -- not strictly necessary to support 'private' methods.] An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff all of the following are true: ... ***[Move this up from later in the section:]*** It is a compile-time error if ***the overridden method, mA, is*** a static method. An instance method _mC_, declared in or inherited by class _C_, _overrides from C_ another method, _mI_, declared in interface _I_, iff all of the following are true: - _I_ is a superinterface of _C_. - ***_mI_ is not 'static'.*** - ***_C_ does not inherit _mI_.*** - The signature of _mC_ is a subsignature (8.4.2) of the signature of _mI_. - ***mI is 'public'*** ----- 9.2 The interface inherits, from the interfaces it extends, all members of those interfaces, except for fields, classes, and interfaces that it hides; abstract ***and*** default methods that it overrides (��9.4.1); and ***private and*** static methods. ----- 13.5.3 Adding an 'abstract', ***'private', or 'static'*** method to an interface does not break compatibility with preexisting binaries. [Note: I believe we can make this assertion because "adding a method" means "adding a method that will compile", presumably? Private and static methods can introduce errors if a reference like I.m()V previously resolved to an abstract/default method in a superinterface, and now resolves to the private/static method in I. But that new method won't compile if there's a method with a matching signature in a superinterface of I.] ***The impact of adding a 'default' method to an interface is described in 13.5.6.*** [This should have been here in 8, since 13.5.3 is apparently where the "add a method" refactoring gets covered, consistent with 13.4.6.] ----- 13.5.6 The considerations for changing [delete 'abstract'] method declarations in interfaces include those for [delete 'abstract'] methods in classes, as described in ***13.4.7***, 13.4.14, 13.4.15, 13.4.19, 13.4.21, ***13.4.22,*** and 13.4.23. ----- 15.12.3 The following compile-time information is then associated with the method invocation for use at run time: ... - The invocation mode, computed as follows: [Delete condition about "is a class", raise nested bullets one level up.] -- If the compile-time declaration has the static modifier, then the invocation mode is static. -- Otherwise, if the compile-time declaration has the private modifier, then the invocation mode is nonvirtual. -- Otherwise, if the part of the method invocation before the left parenthesis is of the form super . Identifier or of the form TypeName . super . Identifier, then the invocation mode is super. -- ***Otherwise***, if the qualifying type of the method invocation is an interface, then the invocation mode is interface. -- [List this bullet last] Otherwise, the invocation mode is virtual. ----- 15.12.4.3 For the method 'm': - If m is public, then m is accessible. [Delete parenthetical about members of interfaces being 'public'.]
11-10-2016

Suggested changes for section 9.4: ----- 9.4 InterfaceMethodModifier: one of Annotation 'public' ***'private'*** 'abstract' 'default' 'static' 'strictfp' ... ***A method declared in the body of an interface may be given 'public' or 'private' access (6.6). If no access modifier is provided, the method*** is implicitly 'public'. [Delete the next sentence about redundancy of 'public'.] ***A method declared in the body of an interface may not be given 'protected' or package access.*** A default method is a method that is declared in the body of an interface with the 'default' modifier; its body is always represented by a block. It provides a default implementation for any class that implements the interface without overriding the method. ***[paragraph break]*** Default methods are distinct from concrete methods (8.4.3.1), which are declared in classes. ***They are distinct from 'private' interface methods, which are not inherited nor overridden. And, as instance methods, they are distinct from 'static' methods.*** An interface can declare static methods, which are invoked without reference to a particular object. It is a compile-time error to use the name of a type parameter of any surrounding declaration in the header or body of a 'static' method of an interface. The effect of the 'strictfp' modifier is to make all float or double expressions within the body of a default or static method be explicitly FP-strict (��15.4). An interface method lacking a 'default' modifier, ***a 'private' modifier,*** or a 'static' modifier is implicitly 'abstract'. [Delete aside about abstract method bodies, which is just a forward reference to 9.4.3.] It is permitted [Delete "but discouraged as a matter of style"?] to redundantly specify the 'abstract' modifier for such a method declaration. ***A method declared in the body of an interface may not be declared 'final', 'synchronized', or 'native'.*** [This is redundant, but it helps to clarify that the omission is intentional.] It is a compile-time error if the same keyword appears more than once as a modifier for a method declaration in an interface. It is a compile-time error if a method is declared with more than one of the modifiers 'abstract', 'default', or 'static'. ***It is a compile-time error if a method is declared both 'private' and 'abstract', or both 'private' and 'default'.*** A method may be declared both 'private' and 'static'. ... ----- 9.4.1 ... An interface does not inherit ***'private' or*** 'static' methods from its superinterfaces. If an interface _I_ declares a ***'private' or*** 'static' method _m_, and the signature of _m_ is a subsignature of ***a 'public'*** instance method _m'_ in a superinterface of _I_, and _m'_ would otherwise be accessible to code in _I_, then a compile-time error occurs. In essence, a ***'private' or*** 'static' method in an interface cannot ***"override" or*** "hide" an instance method in a superinterface. This is similar to the rule in 8.4.8.2 whereby a 'static' method in a class cannot hide an instance method in a superclass or superinterface. Note that the rule in 8.4.8.2 speaks of a class that "declares or inherits a static method", whereas the rule above speaks only of an interface that "declares a static method", since an interface cannot inherit a static method. Also note that the rule in 8.4.8.2 allows hiding of both instance and static methods in superclasses/superinterfaces, whereas the rule above considers only ***public*** instance methods in superinterfaces. ----- 9.4.1.1 An instance method _m1_, declared in or inherited by an interface _I_, _overrides from I_ another instance method, _m2_, declared in interface _J_, iff ***all*** of the following are true: - _I_ is a subinterface of _J_. - ***_I_ does not inherit _m2_.*** [Not related to private methods, but should be here; compare 8.4.8.1.] - The signature of _m1_ is a subsignature (8.4.2) of the signature of _m2_. - ***m2 is 'public'*** ... ----- 9.4.3 A default method has a block body. This block of code provides an implementation of the method in the event that a class implements the interface but does not provide its own implementation of the method. A ***'private' or a*** 'static' method also has a block body, which provides the implementation of the method. It is a compile-time error if an interface method declaration is 'abstract' (explicitly or implicitly) and has a block for its body. It is a compile-time error if an interface method declaration is 'default', ***'private',*** or 'static' and has a semicolon for its body.
11-10-2016

The Description's goal of a private method not being a default method isn't fully realized by the 9.4 change, which can be read as making default methods distinct only from "private and static interface methods" a.k.a. 'private static void m() {}'. Suggest "Default methods, being instance methods, are distinct from /static/ interface methods. Default methods, which are inherited (9.4.1), are also distinct from /private/ interface methods, which are not inherited." (Yes, a private static interface method is caught twice, but I think the sentence is clearer than "private and static interface methods", especially when a later sentence uses that phrase to mean 'really, both modifiers': "A method may be declared both 'private' and 'static'.") ALSO: It would be good to relocate the compile-time error re: instance-overriding-static to be closer to the class/class scenario in 8.4.8.1, and to then phrase the error w.r.t. mA and mC.
07-10-2016

The 8.4.8.1 use of "instance method" for interface overriding but not class overriding is intentional, but too subtle. I've changed it, putting back the rule about abstract/default methods, but making it more explicit about what we're after: "_mI_ is not 'static'." Why the discrepancy? Because static interface methods are not inherited, while static class methods are. Overriding a static class method sets you up for the next sentence: "It is a compile-time error if an instance method overrides a static method."
06-10-2016

Is this method implicitly abstract? private void m() {} If I don't include 'private' in the list of modifiers that prevent the method from being considered abstract (9.4), then it will be abstract, per that rule. As you point out, Alex, this will lead to a compiler error. But that's not what we want���it's a legal declaration!
06-10-2016

I'd prefer 9.4 to be as explicit as possible so that you don't need to join the dots with clauses later in 9.4, or in clauses in 9.4.3, to figure out that a private interface method must have a body and can never be abstract. But you could also address the statement in 9.4 by saying that "An interface method with a semi-colon for its body is implicitly abstract." and then tweak 9.4.3 to cover which declarations are required to have semi-colon or block bodies.
05-10-2016

- 9.4 says "An interface method lacking a 'default' modifier, ***a 'private' modifier,*** or a 'static' modifier is implicitly 'abstract'." but one of these things (private) is not like the others (default, static, abstract). I'd prefer to not mention private here. If someone then thinks that a non-default non-static method can embody abstractness while also having a private modifier, then they will be set straight by a later rule ("It is a compile-time error if a method is declared both private and abstract, or both private and default.".) - 8.4.8.1 says "An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff ...". No mention of mA being an instance method. But for the cleanup of 8.4.8.1 in a comment above, mI declared in an interface is specified to be an instance method. Please clarify for mA.
05-10-2016

The above spec text has been updated to address all previous comments.
03-10-2016

Please also specify if private and/or static methods are allowed to be declared to be final. This request has come in from the VM team via JDK-8166422
26-09-2016

Maybe jls-9.2-110 should also mention private methods. What do you think? "The interface inherits, from the interfaces it extends, all members of those interfaces, except for fields, classes, and interfaces that it hides; abstract or default methods that it overrides (��9.4.1); ***private and*** static methods."
21-04-2015

Per feedback from the JCK team (Thanks Georgiy Rakov), the following sections need to be looked into too: jls-15.12.3-500-E-B: "If the qualifying type of the method invocation is an interface, then the invocation mode is interface." Should this be enhanced for the cases of private and static methods of the interface? jls-15.12.4.3-130-B-1: "If m is public, then m is accessible. (All members of interfaces are public (��9.2))" Private methods should be taken into account? jls-6.6.1-100-D-D "Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class (��7.6) that encloses the declaration of the member or constructor" Private methods should be also accessible in the interface?
02-03-2015