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 - 9.6.1 - 8.1.1.1 - 8.1.3 - 8.1.5 - 8.4.3.1 - 8.4.8 - 8.4.8.1 - 8.4.8.2 - 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 - 15.12.4.4 - 6
Version 0.9.3. Copyright © 2014 Oracle America, Inc. Legal Notice.
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 superclass method overrides the superinterface 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.
This error condition can be avoided by declaring a new method that overrides, and thus prevents the inheritance of, all conflicting methods.
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.
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 abstract methods; 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.
...
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.
Compare JLS 9.1.4
...
InterfaceMemberDeclaration: ConstantDeclarationAbstractMethodDeclarationInterfaceMethodDeclaration ClassDeclaration InterfaceDeclaration ';'
...
Compare JLS 9.2
The members of an interface are: [jls-9.2-100]
public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface. [jls-9.2-100-C]
It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final in Object. [jls-9.2-100-C.1]
It follows that it is a compile-time error if the interface declares a method with a signature that is override-equivalent (8.4.2) to a public method of Object, but has a different return type, or has an incompatible throws clause, or is not abstract. [jls-9.2-100-C.2]
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.
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 modifier for a method declared in an interface.
abstract
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. Default methods are distinct from concrete methods (8.4.3.1), which are declared in classes. [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 . [jls-9.4-210]
static methods cannot be abstract
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]
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]
static method declared in I has a signature that is a subsignature (8.4.2) of the signature of m. [jsr335-9.4.1-100-B]
An interface does not inherit static methods from its superinterfaces. [jsr335-9.4.1-15]
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.
...
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]
These error conditions can be avoided by declaring a new method that overrides, and thus prevents the inheritance of, all conflicting methods.
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 areabstractand thus contain no implementation" should be removed and replaced to include examples of default methods overriding abstract methods and vice versa.
Discussion and motivation:
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
Childabove inheritsJ.namefromJbut notI.namefromK, becauseI.namehas already been overridden byJ.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 instance 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 instance methods.
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:
The prohibition against declaring one of the
Objectmethods as a default method may be surprising. There are, after all, cases likejava.util.Listin which the behavior oftoStringandequalsare 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
toStringdefault. 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 fortoStringdeclared inObjectandtoStringdeclared 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.- Third, use cases for declaring
Objectmethods in interfaces typically assume a linear interface hierarchy; the feature does not generalize very well to multiple inheritance scenarios.- Fourth, the
Objectmethods are so fundamental that it seems dangerous to allow an arbitrary superinterface to silently add a default method that changes their behavior.The interface is free, however, to define another method that provides behavior useful for classes that override the
For further discussion, see http://mail.openjdk.java.net/pipermail/lambda-dev/2013-March/008435.html.Objectmethods. For example, thejava.util.Listinterface could declare aelementStringmethod that produces the string described by the contract oftoString; implementors could then simply delegate to this method.
Compare JLS 9.6
...
AnnotationTypeDeclaration:
InterfaceModifiersopt '@' 'interface' Identifier AnnotationTypeBody
AnnotationTypeBody:
'{' AnnotationTypeElementMemberDeclarationsopt '}'
AnnotationTypeElementMemberDeclarations:
AnnotationTypeElementMemberDeclaration
AnnotationTypeElementMemberDeclarations AnnotationTypeElementMemberDeclaration
...
Discussion and motivation:
The renamings and restructurings in this and the next section are simply for clarification.
Compare JLS 9.6.1
...
AnnotationTypeElementMemberDeclaration: AnnotationTypeElementDeclaration ConstantDeclaration ClassDeclaration InterfaceDeclarationEnumDeclarationAnnotationTypeDeclaration';' AnnotationTypeElementDeclaration:AbstractMethodModifiersoptAnnotationTypeElementModifiersopt Type Identifier '(' ')' Dimsopt DefaultValueopt ';' AnnotationTypeElementModifiers: AnnotationTypeElementModifier AnnotationTypeElementModifiers AnnotationTypeElementModifier AnnotationTypeElementModifier: one of Annotation 'public' 'abstract' DefaultValue: 'default' ElementValue
...
Discussion and motivation:
A few changes are made here for clarification, but the only substantial change is to introduce the production
AnnotationTypeElementModifiersto replaceAbstractMethodModifiers(now renamedInterfaceMethodModifiers). This is to avoid allowing the new interface method modifiers on annotation type element declarations.While we've expanded the variety of methods that can be declared in interfaces in general (including
staticmethods anddefaultmethods), to avoid confusion we prefer not to expand the variety of methods that can be declared in annotation types.Note that is is still possible, however, for an annotation type to inherit a default method from its implicit superinterface,
Annotation(though no such default method exists currently).
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]
abstract. [jsr335-8.1.1.1-200-A]
abstract method declared with package access, and there exists no method that overrides the abstract method from C or from a superclass of C. [jsr335-8.1.1.1-200-B]
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:
These changes are not meant to substantively change the definition of an abstract class, but rather to clarify the existing meaning. We interpret the previous clause requiring that, for every abstract method, C "declares [or] inherits a method that implements it", to mean that the abstract method is overridden in C or in some supertype of C (and thus the abstract method would not be inherited by C).
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 or interface 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]
...
Discussion and motivation:
It is unusual, but possible, for an enclosing type of an inner class to be an interface. Such a class can only be declared inside of a default method body (9.4). This includes, for example, the following cases:
Note that only the outermost enclosing type declaration of an inner class can be an interface—all other enclosing type declarations are inner classes, and it is impossible to declare an "inner interface."
- An anonymous class declared in a default method body.
- A local class declared in a default method body.
- A member class of an anonymous class declared in a default method body.
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]
...
abstract Methods [Addendum] See JLS 8.4.3.1
If a method declared by a class is not abstract, it may be referred to as a concrete method. [jsr335-8.4.3.1-10]
Compare JLS 8.4.8
A class C inherits from its direct superclass and direct superinterfaces all concrete (both static and instance) methods m of the superclass abstract and non-abstractand superinterfaces for which all of the following are true: [jls-8.4.8-100]
public, protected, or declared with
A class does not inherit static methods from its superinterfaces. [jsr335-8.4.8-15]
A class C inherits from its direct superclass and direct superinterfaces all abstract and default (9.4) methods m for which all of the following are true: [jsr335-8.4.8-20]
public, protected, or declared with 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:
This definition of inheritance achieves two goals:
- Clarify that it is possible for an inherited concrete method to prevent the inheritance of an abstract or default method. (Later we will assert that the concrete method overrides the abstract or default method "from C".) This has always been the case (for abstract methods), 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.
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.
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]
public. [jls-8.4.8.1-100-C-1]
protected. [jsr335-8.4.8.1-100-C-3]
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]
abstract or default method. [jsr335-8.4.8.1-20-C]
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]
...
Discussion and motivation:
Previously, the overriding relationship between a method declared in a class and a method declared in an interface was unspecified. That has been fixed. Most of the other changes here are to extend the notion of overriding to handle methods that override another from some subclass of their declaring class. This can happen in two ways:
- A concrete instance method in a generic superclass can, under certain parameterizations, have the same signature as an abstract method in that class. In this case, the concrete method is inherited and the abstract method is not (as described above). The inherited method should then be considered to override its abstract peer from C. (This scenario is complicated by package access: if C is in a different package, then m2 would not have been inherited anyway, and should not be considered overridden.)
- An inherited superclass method can override a superinterface method. (Happily, package access is not a concern here.)
Compare JLS 8.4.8.2
If a class C declares or inherits a static method m, then the declaration m is said to hide in C any method m', where the signature of m is a subsignature (8.4.2) of the signature of m', in the superclasses and superinterfaces of the class C that would otherwise be accessible to code in the class C. [jls-8.4.8.2-100]
It is a compile-time error if a static method hides an instance method. [jls-8.4.8.2-110]
...
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: [jls-8.4.8.4-120]
If one of the inherited methods is not
abstract, ... [jls-8.4.8.4-120-A]
If all the inherited methods are Otherwise, the set of override-equivalent methods consists of at least one abstractabstract method and zero or more default methods; then the class is necessarily an abstract class and is considered to inherit all the methods. [jls-8.4.8.4-120-B]
abstract
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]
These error conditions can be avoided by declaring a new method that overrides, and thus prevents the inheritance of, all conflicting methods.
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:
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.
An exception to the strict default-abstract and default-default conflict rules is made when anabstractmethod 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 superclass 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.
Compare JLS 15.8
...
PrimaryNoNewArray: Literal Type '.' 'class' 'void' '.' 'class' 'this'ClassNameTypeName '.' 'this' ...
...
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]
...
Discussion and motivation:
Default methods provide the unique ability to accessthisinside of an interface. (All other interface members are either abstract methods orstatic. As a result, it is possible forthisto have an interface type.
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]
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).
...
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 ')'
...
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]
. Identifier, then the name of the method is the Identifier and the If TypeName is the name of an interface rather than a class, then a compile-time error occurs, because this form can invoke only static methods and interfaces have no static methods. [jls-15.12.1-100-A-2.1]
. Identifier. ... [jls-15.12.1-100-A-3]. NonWildTypeArgumentsopt Identifier, ... [jls-15.12.1-100-B]super . NonWildTypeArgumentsopt Identifier, then the name of the method is the Identifier and the class to be searched is the superclass of the class whose declaration contains the method invocation. [jls-15.12.1-100-C]
Let T be the type declaration immediately enclosing the method invocation. It is a compile-time error if T is the class Object or T is an interface. [jls-15.12.1-100-C.1]
. super . NonWildTypeArgumentsopt Identifier, then the name of the method is the Identifier. [jls-15.12.1-100-D]
It is a compile-time error if TypeName denotes neither a class nor an interface. [jsr335-15.12.1-100-Y]
If TypeName denotes a class, C, then the class to be searched is the superclass of C. [jls-15.12.1-100-D']
It is a compile-time error if C is not a lexically enclosing class of the current class. [jls-15.12.1-100-D.1]
It is a compile-time error if C is the class Object. [jls-15.12.1-100-D.2]
Otherwise, TypeName denotes the interface to be searched, I. [jsr335-15.12.1-100-Z]
Let T be the type declaration immediately enclosing the method invocation. It is a compile-time error if I is not a direct superinterface of T, or if there exists some other direct superclass or direct superinterface of T, J, such that J is a subtype of I. [jsr335-15.12.1-100-Z1]
Let T be the type declaration immediately enclosing the method invocation. It is a compile-time error if T is the class Object or T is an interface. [jls-15.12.1-100-D.3]
. NonWildTypeArguments Identifier, then the name of the method is the Identifier and the If TypeName is the name of an interface rather than a class, then a compile-time error occurs, because this form can invoke only static methods and interfaces have no static methods. [jls-15.12.1-100-E.1]
Discussion and motivation:
The TypeName
.supersyntax 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 unqualifiedsuperfrom 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 { default void foo() { 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
.superfrom 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 interfacesupercall.
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]
abstractabstract or default, and the signatures of all the maximally specific methods have the same erasure (4.6), then the most specific method is chosen arbitrarily among the subset of the maximally specific methods that have the most specific return type. [jls-15.12.2.5-530-A-2] However, the most specific method is considered i) to be abstract, and ii) to throw a checked exception if and only if that exception or its erasure is declared in the throws clauses of each of the maximally specific methods. [jls-15.12.2.5-530-A-2.1]
Compare JLS 15.12.3
...
If the method invocation has, before the left parenthesis, the form ExpressionName . NonWildTypeArgumentsopt Identifier or Primary . NonWildTypeArgumentsopt Identifier, then the compile-time declaration must not be a static method declared in an interface, or a compile-time error occurs. [jsr335-15.12.3-10]
...
If the method invocation has, before the left parenthesis, the form ClassName TypeName . super . NonWildTypeArgumentsopt Identifier, then: [jls-15.12.3-140]
abstract, a compile-time error occurs. [jls-15.12.3-140-A]
The previous check is redundant: the same error is asserted in 15.12.1.
...
Discussion and motivation:
In the case that a superinterface overrides a method declared 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 asupermethod invocation.)
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]
...
. super, is involved, then if TypeName denotes a class, the target reference is the value of . this; otherwise, the target reference is the value of this. [jls-15.12.4.1-120-D]
...
Compare JLS 15.12.4.4
...
The dynamic method lookup uses the following procedure to search class S, and then the superclasses and superinterfaces of class S, as necessary, for method m. [jls-15.12.4.4-230]
Let X be the compile-time type of the target reference of the method invocation. Then: [jls-15.12.4.4-240]
abstractsuper or interface, then this is the method to be invoked, and the procedure terminates. [jls-15.12.4.4-240-A-1]
virtual, and the accessibility of m is such that the declaration in S virtual, and the declaration in S does not override X.m, and moreover X.m is declared abstract, then an AbstractMethodError is thrown. [jls-15.12.4.4-240-A-3]static; iv) for each method, where the method's declaring interface is I, there is no other method satisfying (i) through (iii) that is declared in a subinterface of I. If this set contains a default method, one such method is the method to be invoked. Otherwise, an abstract method in the set is selected as the method to be invoked. [jsr335-15.12.4.4-240-C]
After dynamic method lookup, various errors may occur: [jsr335-15.12.4.4-242]
abstract, an AbstractMethodError is thrown. [jsr335-15.12.4.4-242-A]
default, and more than one default method appears in the set of candidates in step 3, above, an IncompatibleClassChangeError is thrown. [jsr335-15.12.4.4-242-B]
interface and the selected method is not public, an IllegalAccessError is thrown. [jsr335-15.12.4.4-242-C]
The above procedure (if it terminates without error) will find a non-abstract, accessible method to invoke, provided that all classes and interfaces in the program have been consistently compiled. However, if this is not the case, then various errors may occur. The specification of additional details of the behavior of a Java virtual machine under these circumstances is are given by The Java Virtual Machine Specification.
...
Discussion and motivation:
The substantial change here is to explain how a default method may be selected for invocation, and it mirrors the JVM selection behavior described in Part J. Additional changes are made as bug fixes, for correctness. Specifically:
- It was incorrect to say that only non-
abstractmethods would be matched by the search.- Because overriding, as defined in 8.4.8.1, may involve generic substitution and other type analysis, it is more precise to say simply that
virtualinvocation will test for appropriate accessibility.- When, during a
virtualsearch, a matching method does not override m, it is not the case that an error occurs—instead, the search continues.- Given consistently-compiled classes, the type checker has already proven that no runtime error will occur. So there is no need for the "if it terminates without error" qualifier.
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.
...
Compare JLS 6.6.1
public, then it may be accessed by any code, provided that the compilation unit (7.3) in which it is declared is observable. [jls-6.6.1-100-B] If a top level class or interface type is not declared declared with package access, then it may be accessed only from within the package in which it is declared. [jls-6.6.1-100-B.1]public
A class or interface declared without an access modifier implicitly has package access. [jsr335-6.6.1-100-B.2]
public, then access is permitted. [jls-6.6.1-100-D-1] All members of interfaces lacking access modifiers are implicitly public. [jls-6.6.1-100-D-1.1]
protected, then access is permitted only when one of the following is true: [jls-6.6.1-100-D-2]
A class member or constructor declared without an access modifier implicitly has package access. [jsr335-6.6.1-100-D-4.1]
private, ...
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.
...
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).
...
Compare JLS 13.5.3
Adding an abstract method to an interface does not break compatibility with pre-existing binaries.
...
abstractCompare JLS 13.5.6
The considerations for changing abstract method declarations in interfaces are the same as include those for abstract methods in classes, as described in 13.4.14, 13.4.15, 13.4.19, 13.4.21, and 13.4.23.
Adding a default method, or changing a method from abstract to default, does not break linkage compatibility with pre-existing binaries, but may cause an IncompatibleClassChangeError if a pre-existing binary attempts to invoke the method. This error occurs if the qualifying type, T, is a subtype of two interfaces, I and J, where both I and J declare a default method with the same signature and result type, and neither I nor J is a subinterface of the other.
Discussion and motivation:
Strictly speaking, adding a default method is a binary-compatible change, even if it introduces errors at compile time or invocation time, because it does not introduce errors at link time.
Practically speaking, the risk of accidental clashes occurring by introducing a default method are similar to those associated with adding a new method to a non-
finalclass. (In the event of a clash, adding a method to a class is unlikely to trigger aLinkageError, but an accidental override of the method in a child can lead to unpredictable method behavior. Both changes can cause errors at compile time.)The following illustrates how adding a default method can result in an invocation-time error.
interface Painter { default void draw() { System.out.println("Here's a picture..."); } } interface Cowboy { } class CowboyArtist implements Cowboy, Painter { public static void main(String... args) { new CowboyArtist().draw(); } }Running
CowboyArtistwill printHere's a picture....Now consider a scenario in which a default method is added to
Cowboywithout recompilingCowboyArtist.interface Cowboy { default void draw() { System.out.println("Bang!"); } }The class
CowboyArtistwill link without error, but running themainmethod will result in anIncompatibleClassChangeError.