Lambda Specification, Part H: Default Methods

Navigation: Overview - Part A - Part B - Part C - Part D - Part E - Part F - Part G - Part H - Part J
Sections: 9 - 9.1.1.2 - 9.1.4 - 9.2 - 9.4 - 9.4.1 - 9.4.3 - 9.6.1 - 8.1.1.1 - 8.1.3 - 8.1.5 - 8.4.8 - 8.4.8.1 - 8.4.8.4 - 8.8.7.1 - 15.8 - 15.8.3 - 15.8.4 - 15.11.2 - 15.12 - 15.12.1 - 15.12.2.5 - 15.12.3 - 15.12.4.1 - 6 - 6.6.1 - 7.6 - 8.1.1
Version 0.6.1. Copyright © 2012 Oracle America, Inc. Legal Notice.

Summary

A default method is a method that is declared in an interface with the modifier default. Its body provides a default implementation for any class that implements the interface without overriding the method. This allows new functionality to be added to existing (and perhaps already widely-distributed) interfaces. More generally, it provides a mechanism for multiple inheritance of behavior.

An interface may also declare static methods, which work in much the same way as static methods in classes, except that they are not inherited. Often, an interface is the most appropriate place to declare methods that produce or manipulate objects of the interface type.

An interface method that is neither default nor static is implicitly abstract.

An interface I inherits from its direct superinterfaces all abstract and default methods that are members of a superinterface, not overridden by a declaration in I, and not already overridden by another method in a superinterface of I.

Similarly, a class C inherits from its direct superclass and direct superinterfaces all abstract and default methods that are members of a supertype, not overridden by a declaration in C nor a concrete method inherited from the superclass of C, and not already overridden by another method in a supertype of C.

Notably, this implies that a method inherited from a superclass of C can override a default or abstract method in a superinterface of C. We say the class method overrides the interface method from C. In contrast, an inherited interface method never overrides any methods other than those already overridden at its declaration site.

It is a compile-time error if I or C inherits a default method whose signature is override-equivalent with another method inherited by I. This is the case whether the other method is abstract or not.

An overridden default method can be accessed by using a method invocation expression of the form InterfaceName.super.m(). The named interface must be a direct superinterface of the type declaration immediately enclosing the expression.

A this expression may appear in a default method body; its type is the type of the enclosing interface. Similarly, an anonymous or local class may be declared in a default method body, so the enclosing instance of an inner class may have an interface type.

To avoid confusion with the default modifier, the access level given implicitly to unmodified declarations in classes is now referred to as package access rather than default access; the package modifier may be used to explicitly indicate this access level.

9 Interfaces [Modified]

Compare JLS 9

An interface declaration introduces a new reference type whose members are classes, interfaces, constants, and abstract methods. This type has no implementation instance variables, and typically declares one or more methods that lack an implementation; otherwise unrelated classes can implement the interface by providing implementations for its abstract methods. Interfaces may not be directly instantiated.

...

An interface may be declared to be a direct extension of one or more other interfaces, meaning that it implicitly specifies inherits all the member types, abstract instance methods, and constants of the interfaces it extends, except for any members that it may override or hide.

A class may be declared to directly implement one or more interfaces, meaning that any instance of the class implements all the abstract methods specified by the interface or interfaces. A class necessarily implements all the interfaces that its direct superclasses and direct superinterfaces do. This (multiple) interface inheritance allows objects to support (multiple) common behaviors without sharing any implementation a superclass.

...

9.1.1.2 strictfp Interfaces [Modified]

Compare JLS 9.1.1.2

The effect of the strictfp modifier is to make all float or double expressions within the interface declaration be explicitly FP-strict (15.4). [jls-9.1.1.2-100]

This implies that all methods declared in the interface, and all nested types declared in the interface, are implicitly strictfp. [jls-9.1.1.2-110]

The previous sentence mimics 8.1.1.3.

9.1.4 Interface Body and Member Declarations [Modified]

Compare JLS 9.1.4

...

InterfaceMemberDeclaration:
  ConstantDeclaration
  AbstractMethodDeclaration
  InterfaceMethodDeclaration
  ClassDeclaration
  InterfaceDeclaration
  ';'

...

9.2 Interface Members [Modified]

Compare JLS 9.2

The members of an interface are: [jls-9.2-100]

The interface inherits, from the interfaces it extends, all members of those interfaces, except for fields, classes, and interfaces that it hides, and abstract or default methods that it overrides, and static methods. [jls-9.2-110]

Fields, methods, and member types of an interface type may have the same name, since they are used in different contexts and are disambiguated by different lookup procedures (6.5). However, this is discouraged as a matter of style.

9.4 Abstract Method Declarations [Modified]

Compare JLS 9.4

InterfaceMethodDeclaration:
  InterfaceMethodModifiersopt TypeParametersopt Result
                      MethodDeclarator Throwsopt MethodBody

InterfaceMethodModifiers:
  InterfaceMethodModifier
  InterfaceMethodModifiers InterfaceMethodModifier

InterfaceMethodModifier: one of
  Annotation 'public' 'abstract' 'default' 'static' 'strictfp'

The following is repeated from 8.4.7 to make the presentation here clearer:

MethodBody:
  Block
  ';'

If an annotation a (9.7) on a method declaration corresponds to an annotation type T (9.6) and T has a (meta-)annotation m that corresponds to java.lang.annotation.Target, then m must have an element whose value is java.lang.annotation.ElementType.METHOD, or a compile-time error occurs. [jls-9.4-110]

Every method declaration in the body of an interface is implicitly public (6.6). [jls-9.4-120]

It is permitted, but discouraged as a matter of style, to redundantly specify the public and/or abstract modifier for a method declared in an interface.

A default method is a method that is declared in 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. [jsr335-9.4-125]

An interface can declare static methods, which are invoked without reference to a particular object. [jsr335-9.4-127]

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. [jsr335-9.4-128]

The previous sentence mimics 8.4.3.2.

An interface method lacking a default modifier or a static modifier is implicitly abstract, so its body is always represented by a semicolon, not a block. The declaration may optionally include the abstract keyword. [jls-9.4-130]

The effect of the strictfp modifier is to make all float or double expressions within the method body be explicitly FP-strict (15.4). [jsr335-9.4-135]

The previous sentence mimics 8.4.3.5.

It is a compile-time error if the same modifier appears more than once on a method declared in an interface. [jls-9.4-200]

It is a compile-time error if a method is declared with more than one of the modifiers abstract, default, or static. [jsr335-9.4-202]

It is a compile-time error if an abstract method declaration contains the keyword strictfp. [jsr335-9.4-205]

It is a compile-time error if a method declared in an interface is declared native, synchronized, or final because static methods cannot be abstract. [jls-9.4-210]

It is a compile-time error if a method declared in an interface is strictfp or native or synchronized because those keywords describe implementation properties rather than interface properties. [jls-9.4-220]

However, a method declared in an interface may be implemented by a method that is declared strictfp or native or synchronized in a class that implements the interface.

It is a compile-time error if a method declared in an interface is declared final. [jls-9.4-240]

However, a method declared in an interface may be implemented by a method that is declared final in a class that implements the interface.

It is a compile-time error for the body of an interface to declare, explicitly or implicitly, two methods with override-equivalent signatures (8.4.2). [jls-9.4-260]

However, an interface may inherit several abstract methods with such signatures (9.4.1).

A method in an interface may be generic. The rules for type parameters of a generic method in an interface are the same as for a generic method in a class. [jls-9.4-300]

9.4.1 Inheritance and Overriding [Modified]

Compare JLS 9.4.1

An interface I inherits from its direct superinterfaces all abstract and default methods m for which all of the following are true: [jls-9.4.1-100]

An interface does not inherit static methods from its superinterfaces.

An instance method m1, declared or inherited by an interface I, overrides from I another instance method, m2, declared in interface J, iff both of the following are true: [jls-9.4.1.1-100]

An overridden default method can be accessed by using a method invocation expression (15.12) that contains the keyword super qualified by a superinterface name.

The previous sentence mimics 8.4.8.1.

It is a compile-time error if an interface declares a static method whose signature is a subsignature of an instance method inherited from a superinterface. [jsr335-9.4.1-10]

If a method declaration d1 with return type R1 overrides or hides the declaration of another method d2 with return type R2, then d1 must be return-type-substitutable (8.4.5) for d2, or a compile-time error occurs. [jls-9.4.1.2-100]

Furthermore, if R1 is not a subtype of R2, a compile-time unchecked warning occurs. [jls-9.4.1.2-110]

Moreover, a method declaration must not have a throws clause that conflicts (8.4.6) with that of any method that it overrides; otherwise, a compile-time error occurs. [jls-9.4.1.2-200]

The presence or absence of the strictfp modifier has absolutely no effect on the rules for overriding methods. For example, it is permitted for a method that is not FP-strict to override an FP-strict method and it is permitted for an FP-strict method to override a method that is not FP-strict.

The previous paragraph mimics 8.4.8.1.

...

An interface inherits from its direct superinterfaces all methods of the superinterfaces that are not overridden by a declaration in the interface.

It is possible for an interface to inherit several methods with override-equivalent signatures (8.4.2).

It is a compile-time error if an interface I inherits a default method whose signature is override-equivalent with another method inherited by I. This is the case whether the other method is abstract or default. [jsr335-9.4.1-50]

Otherwise, all the inherited methods are abstract, and the interface is considered to inherit all the methods. [jls-9.4.1.3-100]

However, one of the inherited methods must be return-type-substitutable for every other inherited method; otherwise, a compile-time error occurs. (The throws clauses do not cause errors in this case.) [jls-9.4.1.3-110]

There might be several paths by which the same method declaration is inherited from an interface. This fact causes no difficulty and never, of itself, results in a compile-time error.

The example stating that "methods declared in interfaces are abstract and thus contain no implementation" should be removed and replaced to include examples of default methods overriding abstract methods and vice versa.
Discussion and motivation:
  1. The third clause in the inheritance definition prevents a subinterface from re-inheriting a method that has already been overridden by another of its superinterfaces.

    interface I { default String name() { return "unnamed"; } }
    interface J extends I { default String name() { return getClass().getName(); } }
    interface K extends I {}
    
    interface Child extends J, K {}
    

    The interface Child above inherits J.name from J but not I.name from K, because I.name has already been overridden by J.

  2. Naturally, when two different default methods with matching signatures are inherited by a subinterface, there is a behavioral conflict; we actively detect this conflict and notify the developer with an error, rather than waiting for the problem to arise when a concrete class is compiled.

    Similarly, when an abstract and a default method with matching signatures are inherited, we produce an error. In this case, it would be possible to give priority to one or the other—perhaps we would assume that the default method provides a reasonable implementation for the abstract method, too. But this is risky, since other than the coincidental name and signature, we have no reason to believe that the default method behaves consistently with the abstract method's contract—the default method may not have even existed when the subinterface was originally developed. It is safer in this situation to ask the user to actively assert that the default implementation is appropriate (via an overriding declaration).

    In contrast, the longstanding behavior for inherited concrete methods in classes is that they override abstract methods declared in interfaces (see 8.4.8). The same argument about potential contract violation applies here, but in this case there is an inherent imbalance between classes and interfaces. We prefer, in order to preserve the independent nature of class hierarchies, to minimize class-interface clashes by simply giving priority to concrete methods.

9.4.3 Interface Method Body [New]

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 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. [jsr335-9.4.3-10]

It is a compile-time error if an interface method declaration is default or static and has a semicolon for its body. [jsr335-9.4.3-12]

The above mimic 8.4.7.

It is a compile-time error if a default method is override-equivalent with a non-private method of the class Object, because any class implementing the interface will inherit its own implementation of the method. [jsr335-9.4.3-20]

It is a compile-time error for the body of a static method to attempt to reference the current object using the keyword this or the keyword super. [jsr335-9.4.3-22]

If a method is declared void, then its body must not contain any return statement (14.17) that has an Expression, or a compile-time error occurs. [jsr335-9.4.3-30]

If a method is declared to have a return type, then every return statement (14.17) in its body must have an Expression, or a compile-time error occurs. [jsr335-9.4.3-40]

If a method is declared to have a return type, then a compile-time error occurs if the body of the method can complete normally (14.1). [jsr335-9.4.3-50]

The previous three sentences mimic 8.4.7.
Discussion and motivation:
  1. The prohibition against declaring one of the Object methods as a default method may be surprising. There are, after all, cases like java.util.List in which the behavior of toString and equals are precisely defined. The motivation becomes clearer, however, when some broader design decisions are well-understood:
    • First, methods inherited from a superclass are allowed to override methods inherited from superinterfaces. So every implementing class would automatically override an interface's toString default. This is Java's longstanding behavior, and it's not something we wish to change with the design of default methods, because that would conflict with the goal of allowing interfaces to unobtrusively evolve, only providing default behavior when the class, through its normal hierarchy, doesn't already have it.
    • Second, interfaces do not inherit from Object, even though they implicitly declare many of the same methods (9.2). So there is no common ancestor for toString declared in Object and toString declared in an interface; at best, if both were candidates for inheritance by a class, they would conflict. Working around this problem would require awkward commingling of the class and interface inheritance trees.

    The interface is free, however, to define another method that provides behavior useful for classes that override the Object methods. For example, the java.util.List interface could declare a elementString method that produces the string described by the contract of toString; implementors could then simply delegate to this method.

9.6.1 Annotation Type Elements [Modified]

Compare JLS 9.6.1

...

AnnotationTypeElementDeclaration:
  AbstractMethodModifiersopt InterfaceMethodModifiersopt
            Type Identifier '(' ')' Dimsopt DefaultValueopt ';'

...

...

8.1.1.1 abstract Classes [Modified]

Compare JLS 8.1.1.1

An abstract class is a class that is incomplete, or to be considered incomplete.

Normal classes may have abstract methods (8.4.3.1, 9.4), that is, methods that are declared but not yet implemented, only if they are abstract classes. [jls-8.1.1.1-110]

If a normal class that is not abstract contains an abstract method, then a compile-time error occurs. [jls-8.1.1.1-120]

...

A class C has abstract methods if any either of the following is true: [jls-8.1.1.1-200]

It is a compile-time error if an attempt is made to create an instance of an abstract class using a class instance creation expression (15.9). [jls-8.1.1.1-300]

...

Discussion and motivation:
  1. These changes are not meant to substantively change the definition of an abstract class, but rather to clarify the existing meaning.

8.1.3 Inner Classes and Enclosing Instances [Modified]

Compare JLS 8.1.3

...

An inner class C is a direct inner class of a class or interface O if O is the immediately lexically enclosing class type declaration of C and the declaration of C does not occur in a static context. [jls-8.1.3-300]

A class C is an inner class of class or interface O if it is either a direct inner class of O or an inner class of an inner class of O. [jls-8.1.3-310]

A class or interface O is the zeroth lexically enclosing class type declaration of itself. [jls-8.1.3-320]

A class O is the n'th lexically enclosing class type declaration of a class C if it is the immediately enclosing class type declaration of the n-1'th lexically enclosing class type declaration of C. [jls-8.1.3-330]

An instance i of a direct inner class C of a class or interface O is associated with an instance of O, known as the immediately enclosing instance of i. The immediately enclosing instance of an object, if any, is determined when the object is created (15.9.2). [jls-8.1.3-400]

...

For every superclass S of C which is itself a direct inner class of a class or interface SO, there is an instance of SO associated with i, known as the immediately enclosing instance of i with respect to S. The immediately enclosing instance of an object with respect to its class' direct superclass, if any, is determined when the superclass constructor is invoked via an explicit constructor invocation statement. [jls-8.1.3-440]

When an inner class (whose declaration does not occur in a static context) refers to an instance variable that is a member of a lexically enclosing class, the variable of the corresponding lexically enclosing instance is used. [jls-8.1.3-500]

...

Similar changes to the lexically enclosing class terminology should be made in 8.8.7.1, 13.1, 15.9.2.
Discussion and motivation:
  1. An anonymous or local class may be declared in a default method body; thus, the enclosing instance of an inner class may have an interface type.

8.1.5 Superinterfaces [Modified]

Compare JLS 8.1.5

...

Unless the class being declared is abstract, all the abstract member methods of each direct superinterface must be implemented (8.4.8.1) either by a declaration in this class or by an existing method declaration inherited from the direct superclass or a direct superinterface, because a class that is not abstract is not permitted to have abstract methods (8.1.1.1). [jls-8.1.5-500]

Each default method (9.4.3) of a superinterface of the class may optionally be overridden by a method in the class; if not, the default method is typically inherited and its behavior is as specified by its default body.

It is permitted for a single method declaration in a class to implement methods of more than one superinterface. [jls-8.1.5-510]

...

8.4.8 Inheritance, Overriding, and Hiding [Modified]

Compare JLS 8.4.8

A class C inherits from its direct superclass and direct superinterfaces all concrete (both static and instance) abstract and non-abstract methods m of the superclass and superinterfaces for which all of the following are true: [jls-8.4.8-100]

A class does not inherit static methods from its superinterfaces.

A class C inherits from its direct superclass and direct superinterfaces all abstract and default methods m for which all of the following are true: [jsr335-8.4.8-20]

If the method not inherited is declared in a class, or the method not inherited is declared in an interface and the new declaration is abstract, then the new declaration is said to override it. [jls-8.4.8-200]

If the method not inherited is abstract and the new declaration is not abstract, then the new declaration is said to implement it. [jls-8.4.8-210]

Discussion and motivation:
  1. This definition of inheritance achieves two goals:
    • Clarify that it is possible for a method inherited from a superclass to prevent the inheritance of a superinterface method. (Later we will assert that the superclass method overrides the superinterface method "from C".) This has always been the case, but it has been poorly specified.
    • Introduce, for classes, the rule that one supertype method can prevent the inheritance of another supertype method if the former "already" overrides the latter. This is the same as the rule for interfaces, and prevents conflicts in which multiple default methods are inherited, even though one implementation is clearly meant to supersede the other.
  2. The definitions of "override" and "implement" retracted here are inconsistent with those in the following section. There doesn't seem to be a need to provide a separate definition here.

8.4.8.1 Overriding (by Instance Methods) [Modified]

Compare JLS 8.4.8.1

An instance method m1, declared or inherited by class C, overrides from C another instance method m2, declared in class A, iff all of the following are true: [jls-8.4.8.1-100]

An instance method m1, declared or inherited by class C, overrides from C another method m2, declared in an interface I, iff all of the following are true: [jsr335-8.4.8.1-20]

If a non-abstract method m1 overrides an abstract method m2 from a class C, then m1 is said to implement m2 from C. [jsr335-8.4.8.1-30]

...

8.4.8.4 Inheriting Methods with Override-Equivalent Signatures [Modified]

Compare JLS 8.4.8.4

It is possible for a class to inherit multiple methods with override-equivalent signatures (8.4.2).

It is a compile-time error if a class C inherits a concrete method whose signature is a subsignature of override-equivalent with another concrete method inherited by C. This can happen if a superclass is generic, and it has two methods that were distinct in the generic declaration, but have the same signature in the particular invocation used. [jls-8.4.8.4-110]

It is a compile-time error if a class C inherits a default method whose signature is override-equivalent with another method inherited by C, unless there exists an abstract method declared in a superclass of C and inherited by C that is override-equivalent with the two methods. [jls-8.4.8.4-112]

Note that this exception does not apply if all override-equivalent abstract methods inherited by C were declared in interfaces.

Otherwise, there are two possible cases:

If one of the inherited methods is not abstract, ... [jls-8.4.8.4-120-A]

If all the inherited methods are abstract Otherwise, the set of override-equivalent methods consists of at least one abstract method and zero or more default methods; then the class is necessarily an abstract class and is considered to inherit all the abstract methods. [jls-8.4.8.4-120-B]

One of the inherited methods must be return-type-substitutable for every other inherited method; otherwise, a compile-time error occurs. (The throws clauses do not cause errors in this case.) [jls-8.4.8.4-120-B.1]

There might be several paths by which the same method declaration might be is inherited from an interface. This fact causes no difficulty and never, of itself, results in a compile-time error.

Discussion and motivation:
  1. This is a dramatic simplification of this section, because the special rule allowing a concrete inherited method to "override" an abstract inherited method was eliminated in favor of a more accurate definition of inheritance (8.4.8). The special rules for this scenario are no longer necessary, because they are covered by the usual rules for overriding (8.4.8.3).

    This section is now small enough that it may be preferable to merge it with another section.

  2. An exception to the strict default-abstract and default-default conflict rules is made when an abstract method is declared in a superclass: this assertion of abstract-ness coming from the superclass hierarchy essentially trumps the default, making the default method act as if it were abstract. However, the abstract class method does not override the default method(s), because interfaces are still allowed to refine the signature of the abstract method coming from the class hierarchy.

15.8 Primary Expressions [Modified]

Compare JLS 15.8

...

PrimaryNoNewArray:
  Literal
  Type '.' 'class'
  'void' '.' 'class'
  'this'
  ClassName TypeName '.' 'this'
  ...

...

15.8.3 this [Modified]

Compare JLS 15.8.3

The keyword this may be used only in the body of an instance method, default method, instance initializer, or constructor, or in the initializer of an instance variable of a class. If it appears anywhere else, a compile-time error occurs. [jls-15.8.3-100]

When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance or default method was invoked (15.12), or to the object being constructed. [jls-15.8.3-200]

Additional text about lambda expressions was added here in Part B, 15.8.3.

The type of this is the class or interface type T within which the keyword this occurs. [jls-15.8.3-210]

At run-time, the class of the actual object referred to may be T, if it is a class type, or a class that is a subtype of T. [jls-15.8.3-220]

...

15.8.4 Qualified this [Modified]

Compare JLS 15.8.4

Any lexically enclosing instance (8.1.3) can be referred to by explicitly qualifying the keyword this.

Let C T be the class type denoted by ClassName TypeName. Let n be an integer such that C T is the n'th lexically enclosing class type declaration of the class or interface in which the qualified this expression appears. [jls-15.8.4-110]

The value of an expression of the form ClassName TypeName . this is the n'th lexically enclosing instance of this. [jls-15.8.4-120]

The type of the expression is C T. [jls-15.8.4-200]

It is a compile-time error if the current class or interface is not an inner class of C T or C T itself. [jls-15.8.4-210]

15.11.2 Accessing Superclass Members using super [Modified]

Compare JLS 15.11.2

...

The forms using the keyword super are valid only in an instance method, instance initializer, constructor, or in the initializer of an instance variable of a class. If they appear anywhere else, a compile-time error occurs. [jls-15.11.2-200]

These are exactly the same situations in which the keyword this may be used in a class declaration (15.8.3).

...

15.12 Method Invocation Expressions [Modified]

Compare JLS 15.12

A method invocation expression is used to invoke a class or instance method.

MethodInvocation:
  MethodName '(' ArgumentListopt ')'
  Primary '.' NonWildTypeArgumentsopt Identifier '(' ArgumentListopt ')'
  'super' '.' NonWildTypeArgumentsopt Identifier '(' ArgumentListopt ')'
  ClassName TypeName '.' 'super' '.'
          NonWildTypeArgumentsopt Identifier '(' ArgumentListopt ')'
  TypeName '.' NonWildTypeArguments Identifier '(' ArgumentListopt ')'

...

15.12.1 Compile-Time Step 1: Determine Class or Interface to Search [Modified]

Compare JLS 15.12.1

The first step in processing a method invocation at compile time is to figure out the name of the method to be invoked and which class or interface to check for definitions of methods of that name. There are several cases to consider, depending on the form that precedes the left parenthesis, as follows. [jls-15.12.1-100]

Discussion and motivation:
  1. The TypeName . super syntax is overloaded: traditionally, the name refers to a lexically enclosing class, and the target is the superclass of this class (i.e., as if the invocation were an unqualified super from the lexically enclosing class).
    class Superclass { void foo() { System.out.println("Hi"); } }
    
    class Subclass1 extends Superclass {
      void foo() { throw new UnsupportedOperationException(); }
      Runnable tweak = new Runnable() {
        void run() {
          Subclass1.super.foo(); // gets the 'println' behavior
        }
      };
    }
    

    To support invocation of default methods in superinterfaces, the name may also refer to a direct superinterface of the current class or interface, and the target is that superinterface.

    interface Superinterface { void foo() default { System.out.println("Hi"); } }
    
    class Subclass2 implements Superinterface {
      void foo() { throw new UnsupportedOperationException(); }
      void tweak() {
        Superinterface.super.foo(); // gets the 'println' behavior
      }
    }
    

    No syntax supports a combination of these forms—invoking a superinterface method of a lexically enclosing class (i.e., as if the invocation were of the form Interface . super from the lexically enclosing class).

    class Subclass3 implements Superinterface {
      void foo() { throw new UnsupportedOperationException(); }
      Runnable tweak = new Runnable() {
        void run() {
          Subclass3.Superinterface.super.foo(); // NOT SUPPORTED
        }
      };
    }
    

    There is unlikely to be much need for such syntax; the workaround is to introduce a private method in the lexically enclosing class that performs the interface super call.

15.12.2.5 Choosing the Most Specific Method [Modified]

Compare JLS 15.12.2.5

...

It is possible that no method is the most specific, because there are two or more methods that are maximally specific. In this case: [jls-15.12.2.5-530]

15.12.3 Compile-Time Step 3: Is the Chosen Method Appropriate? [Modified]

Compare JLS 15.12.3

...

If the method invocation has, before the left parenthesis, the form ClassName TypeName . super . NonWildTypeArgumentsopt Identifier, then: [jls-15.12.3-140]

The following check is redundant: the same error is asserted in 15.12.1.

...

Discussion and motivation:
  1. In the case that a superinterface overrides a method in a grandparent interface, this rule prevents the child from "skipping" the override by simply adding the grandparent to its list of direct superinterfaces. The appropriate way to access functionality of a grandparent is through the direct superinterface, and only if that interface chooses to expose the desired behavior. (Alternately, the developer is free to define his own additional superinterface that exposes the desired behavior with a super method invocation.)

15.12.4.1 Compute Target Reference (If Necessary) [Modified]

Compare JLS 15.12.4.1

There are several cases to consider, depending on which of the five productions for MethodInvocation (15.12) is involved: [jls-15.12.4.1-100]

...

...

6 Names [Modified]

Compare JLS 6

...

Access control (6.6) can be specified in a class, interface, method, or field declaration to control when access to a member is allowed. Access is a different concept from scope. Access specified the part of the program text within which the declared entity can be referred to be a qualified name, a field access expression (15.11), or a method invocation expression (15.12) in which the method is not specified by a simple name. In the absence of an access modifier, most declarations have package access, allowing access anywhere within the package that contains its declaration; other possibilities are public, protected, and private.

...

6.6.1 Determining Accessibility [Modified]

Compare JLS 6.6.1

...

Example 6.6-4. Access to Default Package-Access Fields, Methods, and Constructors

If none of the access modifiers public, protected, or private are specified, a class member or constructor has package access: it is accessible throughout the package that contains the declaration of the class in which the class member is declared, but the class member or constructor is not accessible in any other package.

If a public class has a method or constructor with default package access, then this method or constructor is not accessible to or inherited by a subclass declared outside this package.

...

Incidental uses of the word "default" or "none" in reference to accessibility should also be replaced with "package" in the following sections: 4.4, 7.4.1, 8.4.8.3, 12.3.3, 13, 13.4.7, 15.12.2.1, 15.12.4.3.

7.6 Top Level Type Declarations [Modified]

Compare JLS 7.6

...

By default In the absence of an access modifier, the top level types declared in a package have package access: they are accessible only within the compilation units of that package. but A type may be declared to be public to grant access to the type from code in other packages (6.6, 8.1.1, 9.1.1).

...

8.1.1 Class Modifiers [Modified]

Compare JLS 8.1.1

...

ClassModifier: one of
  Annotation
  'public'
  'protected'
  'package'
  'private'
  'abstract'
  'static'
  'final'
  'strictfp'

...

The access modifier modifiers public and package (6.6) pertains pertain only to top level classes (7.6) and to member classes (8.5), not to local or anonymous classes.

...

Similar changes to the grammar and accompanying discussion for access modifiers should be made in the following sections: 8.3.1, 8.4.3, 8.5.1, 8.8.3, 9.1.1.