This document describes changes to the Java Language Specification as modified by the three specification change documents (i) Contextual Keywords, (ii) Consistent Class and Interface Terminology, and (iii) Local and Nested Static Declarations, to support sealed classes and interfaces, a preview feature of Java SE 16. See JEP 397 for an overview of the feature.
The changes are the same as those in the first preview of Sealed Classes in Java SE 15, except for minor editorial changes and the following:
Clarification of the use of context when applying the lexical grammar, particularly in the identification of contextual keywords (formerly described as "restricted identifiers" and "restricted keywords"). This is detailed in the specification change document Contextual Keywords. The keywords
sealed
,non-sealed
, andpermits
are now defined as new instances of contextual keywords (3.9).This document assumes that the changes detailed in specification change documents Consistent Class and Interface Terminology and Local and Nested Static Declarations have been applied. In particular, this provides support for static declarations in two new positions:
- Local, implicitly-static interfaces and enum classes
- Static members of inner classes
This entails a new requirement that local interfaces are not permitted to be
sealed
. (14.3)To enhance narrowing reference conversion to allow for stricter checking of cast conversions with respect to sealed type hierarchies (5.1.6.1).
Improved the wording regarding implicitly declared permitted direct subclasses of a
sealed
class orsealed
interface (8.1.6, 9.1.4).
A companion specification change document describes the changes needed to the Java Virtual Machine Specification to support sealed classes and interfaces.
Changes are described with respect to existing sections of the JLS. New text is indicated like this and deleted text is indicated like this. Explanation and discussion, as needed, is set aside in grey boxes.
Chapter 3: Lexical Structure
3.9 Keywords
51 character sequences, formed from ASCII characters, are reserved for use as keywords. Another 12 15 character sequences, also formed from ASCII characters, may be interpreted as keywords, depending on the context in which they appear.
A keyword cannot be used as an identifier (3.8).
- Keyword:
- ReservedKeyword
- ContextualKeyword
- ReservedKeyword:
- (one of)
abstract continue for new switch
assert default if package synchronized
boolean do goto private this
break double implements protected throw
byte else import public throws
case enum instanceof return transient
catch extends int short try
char final interface static void
class finally long strictfp volatile
const float native super while
_
(underscore)- ContextualKeyword:
- (one of)
exports opens to var
module provides transitive with
open requires uses yield
sealed non-sealed permits
The keywords
const
andgoto
are reserved, even though they are not currently used. This may allow a Java compiler to produce better error messages if these C++ keywords incorrectly appear in programs. The keyword_
(underscore) is reserved for possible future use in parameter declarations.
A character sequence matching a contextual keyword is not treated as a keyword if any part of the sequence can be combined with the immediately preceding or following characters to form a different token.
So the character sequence
openmodule
is interpreted as a single identifier rather than two contextual keywords, even at the start of a ModuleDeclaration. If two keywords are intended, they must be separated by whitespace or a comment.
Any other character sequence matching a contextual keyword is treated as a keyword if and only if it appears in one of the following contexts of the syntactic grammar:
For
open
andmodule
, when appearing as specified as terminals in a ModuleDeclaration (7.7)For
requires
,exports
,opens
,uses
,provides
,to
, andwith
, when appearing as specified as terminals in a ModuleDirectiveFor
transitive
, when appearing as specified as a terminal in a RequiresModifierThe directive
requires transitive;
does not make use of RequiresModifier, and so in this casetransitive
is interpreted as an identifier.For
var
, when appearing as specified as a terminal in a LocalVariableType (14.4) or a LambdaParameterType (15.27.1)In many other contexts, attempting to use the character sequence
var
as an identifier will cause an error, becausevar
is not a valid TypeIdentifier (3.8).For
yield
, when appearing as specified as a terminal in a YieldStatement (14.21)In many other contexts, attempting to use the character sequence
yield
as an identifier will cause an error, becauseyield
is neither a valid TypeIdentifier nor a valid UnqualifiedMethodIdentifier.For
sealed
,non-sealed
andpermits
, when appearing as specified as non-terminals in a NormalClassDeclaration (8.1) or NormalInterfaceDeclaration (9.1)
While these rules depend on details of the syntactic grammar, a compiler for the Java Programming Language can implement them without fully parsing the input program. For example, a heuristic could be used to track the contextual state of the tokenizer, as long as the heuristic guarantees that valid uses of contextual keywords are tokenized as keywords, and valid uses of identifiers are tokenized as identifiers. Or the compiler could always tokenize a contextual keyword as an identifier, leaving it to the parser to recognize special uses of these identifiers.
A variety of character sequences are sometimes assumed, incorrectly, to be keywords:
Chapter 5: Conversions and Contexts
5.1 Kinds of Conversion
5.1.6.1 Allowed Narrowing Reference Conversion
A narrowing reference conversion exists from reference type S to reference type T if all of the following are true:
S is not a subtype of T (4.10)
If there exists a parameterized type X that is a supertype of T, and a parameterized type Y that is a supertype of S, such that the erasures of X and Y are the same, then X and Y are not provably distinct (4.5).
Using types from the
java.util
package as an example, no narrowing reference conversion exists fromArrayList<String>
toArrayList<Object>
, or vice versa, because the type argumentsString
andObject
are provably distinct. For the same reason, no narrowing reference conversion exists fromArrayList<String>
toList<Object>
, or vice versa. The rejection of provably distinct types is a simple static gate to prevent "stupid" narrowing reference conversions.One of the following cases applies:
1. S and T are class types, and either |S| <:
|T| or |T| <:
|S|.
2. S and T are interface types.
3. S is a class type, T is an interface type, and S does not name a final
class (8.1.1).
4. S is a class type, T is an interface type, and S names a final
class that implements the interface named by T.
5. S is an interface type, T is a class type, and T does not name a final
class.
6. S is an interface type, T is a class type, and T names a final
class that implements the interface named by S.
Both S and T are class or interface types, and S names a class or interface that is not disjoint from the class or interface named by T.
The definition of a class or interface being disjoint from another class or interface is given below.
7. 2. S is the class type Object
or the interface type java.io.Serializable
or Cloneable
(the only interfaces implemented by arrays (10.8)), and T is an array type.
8. 3. S is an array type SC[]
, that is, an array of components of type SC; T is an array type TC[]
, that is, an array of components of type TC; and a narrowing reference conversion exists from SC to TC.
9. 4. S is a type variable, and a narrowing reference conversion exists from the upper bound of S to T.
10. 5. T is a type variable, and either a widening reference conversion or a narrowing reference conversion exists from S to the upper bound of T.
11. 6. S is an intersection type S1 &
... &
Sn, and for all i (1 ≤ i ≤ n), either a widening reference conversion or a narrowing reference conversion exists from Si to T.
12. 7. T is an intersection type T1 &
... &
Tn, and for all i (1 ≤ i ≤ n), either a widening reference conversion or a narrowing reference conversion exists from S to Ti.
A class or interface is said to be disjoint from another class or interface if it can be determined statically that they have no instances in common (other than the null
value). It is defined as follows:
A class named C is disjoint from an interface named I if it is not the case that C
<:
I and one of the following cases applies:C is
final
.C is
sealed
, and all of the permitted direct subclasses of C are disjoint from I.C is freely extensible (8.1.1.2), and I is
sealed
, and C is disjoint from all of the permitted direct subclasses and subinterfaces of I.
Rules (b) and (c) simply unpack the
sealed
hierarchies; the important case is rule (a). Consider the following declarations:As class
C
isfinal
and does not implementI
, there can be no instances ofC
that are also an instance ofI
, so they are disjoint. Hence there is no narrowing reference conversion fromC
toI
.In contrast, consider the following declarations:
Even though class
D
does not implementJ
, it is still possible for an instance ofD
to be an instance ofJ
; for example, if the following declaration has been made (possibly at a later time):For this reason
D
is not disjoint fromJ
, and there is a narrowing reference conversion fromD
toJ
.An interface named I is disjoint from a class named C if C is disjoint from I.
A class named C is disjoint from another class named D if it is not the case that C
<:
D, and it is not the case that D<:
C.An interface named I is disjoint from another interface named J if it is not that case that I
<:
J, and it is not the case that J<:
I, and additionally one of the following cases applies:I is
sealed
, and all of the permitted direct subclasses and subinterfaces of I are disjoint from J.J is
sealed
, and I is disjoint from all the permitted direct subclasses and subinterfaces of J.
This rule entails that no two extensible interfaces (9.1.1.4) are disjoint.
Chapter 6: Names
6.1 Declarations
A declaration introduces an entity into a program and includes an identifier (3.8) that can be used in a name to refer to this entity. The identifier is constrained to be a TypeIdentifier when the entity being introduced is a class, interface, or type parameter.
A declared entity is one of the following:
A module, declared in a
module
declaration (7.7)A package, declared in a
package
declaration (7.4)An imported class or interface, declared in a single-type-import declaration or a type-import-on-demand declaration (7.5.1, 7.5.2)
An imported
static
member, declared in a single-static-import declaration or a static-import-on-demand declaration (7.5.3, 7.5.4)A class, declared by a normal class declaration (8.1) or an enum declaration (8.9)
An interface, declared by a normal interface declaration (9.1) or an annotation declaration (9.6)
A type parameter, declared as part of the declaration of a generic class, interface, method, or constructor (8.1.2, 9.1.2, 8.4.4, 8.8.4)
A member of a reference type (8.2, 9.2, 8.9.3, 9.6, 10.7), one of the following:
A field, one of the following:
A method, one of the following:
An enum constant (8.9.1)
A formal parameter of a method of a class or interface (8.4.1), a constructor of a class (8.8.1), or a lambda expression (15.27.1)
An exception parameter of an exception handler declared in a
catch
clause of atry
statement (14.20)A local variable, one of the following:
A local class (14.3)
Constructors (8.8) are also introduced by declarations, but use the name of the class in which they are declared rather than introducing a new name.
The declaration of a type which is not generic (class C ...
) declares one entity: a non-generic type (C
). A non-generic type is not a raw type, despite the syntactic similarity. In contrast, the declaration of a generic type (class C<T> ...
or interface C<T> ...
) declares two entities: a generic type (C<T>
) and a corresponding non-generic type (C
). In this case, the meaning of the term C
depends on the context where it appears:
If genericity is unimportant, as in the non-generic contexts identified below, the identifier
C
denotes the non-generic typeC
.If genericity is important, as in all contexts from 6.5 except the non-generic contexts, the identifier
C
denotes either:
The declaration of a generic class or interface (
class C<T> ...
orinterface C<T> ...
) (8.1.2, 9.1.2) introduces both a class namedC
and a family of types: rawC
,C<Foo>
,C<Bar>
, etc.When a reference to
C
occurs where genericity is unimportant, identified below as one of the non-generic contexts, the reference toC
denotes the class or interfaceC
. In other contexts, the reference toC
denotes a type, or part of a type, introduced byC
.The
1415 non-generic contexts are as follows:
In a
uses
orprovides
directive in a module declaration (7.7.1)In a single-type-import declaration (7.5.1)
To the left of the
.
in a single-static-import declaration (7.5.3)To the left of the
.
in a static-import-on-demand declaration (7.5.4)In a
permits
clause of asealed
class or interface declaration (8.1.6, 9.1.4).
5.6. To the left of the(
in a constructor declaration (8.8)
6.7. After the@
sign in an annotation (9.7)
7.8. To the left of.class
in a class literal (15.8.2)
8.9. To the left of.this
in a qualifiedthis
expression (15.8.4)
9.10. To the left of.super
in a qualified superclass field access expression (15.11.2)
10.11. To the left of.
Identifier or.super.
Identifier in a qualified method invocation expression (15.12)
11.12. To the left of.super::
in a method reference expression (15.13)
12.13. In a qualified expression name in a postfix expression or atry
-with-resources statement (15.14.1, 14.20.3)
13.14. In athrows
clause of a method or constructor (8.4.6, 8.8.5, 9.4)
14.15. In an exception parameter declaration (14.20)The first
eleventwelve non-generic contexts correspond to the firsteleventwelve syntactic contexts for a TypeName in 6.5.1. Thetwelfththirteenth non-generic context is where a qualified ExpressionName such asC.x
may include a TypeNameC
to denote static member access. The common use of TypeName in thesetwelvethirteen contexts is significant: it indicates that these contexts involve a less-than-first-class use of a type. In contrast, thethirteenthfourteenth andfourteenthfifteenth non-generic contexts employ ClassType, indicating thatthrows
andcatch
clauses use types in a first-class way, in line with, say, field declarations. The characterization of these two contexts as non-generic is due to the fact that an exception type cannot be parameterized (8.1.2).Note that the ClassType production allows annotations, so it is possible to annotate the use of a type in a
throws
orcatch
clause, whereas the TypeName production disallows annotations, so it is not possible to annotate the name of a type in, say, a single-type-import declaration.
...
6.5 Determining the Meaning of a Name
6.5.1 Syntactic Classification of a Name According to Context
A name is syntactically classified as a ModuleName in these contexts:
In a
requires
directive in a module declaration (7.7.1)To the right of
to
in anexports
oropens
directive in a module declaration (7.7.2)
A name is syntactically classified as a PackageName in these contexts:
To the right of
exports
oropens
in a module declarationTo the left of the "
.
" in a qualified PackageName
A name is syntactically classified as a TypeName in these contexts:
To name a class or interface:
In a
uses
orprovides
directive in a module declaration (7.7.1)In a single-type-import declaration (7.5.1)
To the left of the
.
in a single-static-import declaration (7.5.3)To the left of the
.
in a static-import-on-demand declaration (7.5.4)In a
permits
clause of asealed
class or interface declaration (8.1.6, 9.1.4).
5.6. To the left of the(
in a constructor declaration (8.8)6.7. After the@
sign in an annotation (9.7)7.8. To the left of.class
in a class literal (15.8.2)8.9. To the left of.this
in a qualifiedthis
expression (15.8.4)9.10. To the left of.super
in a qualified superclass field access expression (15.11.2)10.11. To the left of.
Identifier or.super.
Identifier in a qualified method invocation expression (15.12)11.12. To the left of.super::
in a method reference expression (15.13)As the Identifier or dotted Identifier sequence that constitutes any ReferenceType (including a ReferenceType to the left of the brackets in an array type, or to the left of the < in a parameterized type, or in a non-wildcard type argument of a parameterized type, or in an
extends
orsuper
clause of a wildcard type argument of a parameterized type) in the 16 contexts where types are used (4.11):In an
extends
orimplements
clause of a class declaration (8.1.4, 8.1.5, 8.5, 9.5)In an
extends
clause of an interface declaration (9.1.3)The return type of a method (8.4, 9.4) (including the type of an element of an annotation interface (9.6.1))
In the
throws
clause of a method or constructor (8.4.6, 8.8.5, 9.4)In an
extends
clause of a type parameter declaration of a generic class, interface, method, or constructor (8.1.2, 9.1.2, 8.4.4, 8.8.4)The type in a field declaration of a class or interface (8.3, 9.3)
The type in a formal parameter declaration of a method, constructor, or lambda expression (8.4.1, 8.8.1, 9.4, 15.27.1)
The type of the receiver parameter of a method (8.4)
The type in a local variable declaration (14.4, 14.14.1, 14.14.2, 14.20.3)
A type in an exception parameter declaration (14.20)
In an explicit type argument list to an explicit constructor invocation statement or class instance creation expression or method invocation expression (8.8.7.1, 15.9, 15.12)
In an unqualified class instance creation expression, either as the class type to be instantiated (15.9) or as the direct superclass or direct superinterface of an anonymous class to be instantiated (15.9.5)
The element type in an array creation expression (15.10.1)
The type in the cast operator of a cast expression (15.16)
The type that follows the
instanceof
relational operator (15.20.2)In a method reference expression (15.13), as the reference type to search for a member method or as the class type or array type to construct.
The extraction of a TypeName from the identifiers of a ReferenceType in the 16 contexts above is intended to apply recursively to all sub-terms of the ReferenceType, such as its element type and any type arguments.
For example, suppose a field declaration uses the type
p.q.Foo[]
. The brackets of the array type are ignored, and the termp.q.Foo
is extracted as a dotted sequence of Identifiers to the left of the brackets in an array type, and classified as a TypeName. A later step determines which ofp
,q
, andFoo
is a type name or a package name.As another example, suppose a cast operator uses the type
p.q.Foo<? extends String>
. The termp.q.Foo
is again extracted as a dotted sequence of Identifier terms, this time to the left of the<
in a parameterized type, and classified as a TypeName. The termString
is extracted as an Identifier in anextends
clause of a wildcard type argument of a parameterized type, and classified as a TypeName.
A name is syntactically classified as an ExpressionName in these contexts:
As the qualifying expression in a qualified superclass constructor invocation (8.8.7.1)
As the qualifying expression in a qualified class instance creation expression (15.9)
As the array reference expression in an array access expression (15.10.3)
As a PostfixExpression (15.14)
As the left-hand operand of an assignment operator (15.26)
As a VariableAccess in a
try
-with-resources statement (14.20.3)
A name is syntactically classified as a MethodName in this context:
- Before the "
(
" in a method invocation expression (15.12)
A name is syntactically classified as a PackageOrTypeName in these contexts:
To the left of the "
.
" in a qualified TypeNameIn a type-import-on-demand declaration (7.5.2)
A name is syntactically classified as an AmbiguousName in these contexts:
To the left of the "
.
" in a qualified ExpressionNameTo the left of the rightmost
.
that occurs before the "(
" in a method invocation expressionTo the left of the "
.
" in a qualified AmbiguousNameIn the default value clause of an annotation type element declaration (9.6.2)
To the right of an "
=
" in an an element-value pair (9.7.1)To the left of
::
in a method reference expression (15.13)
The effect of syntactic classification is to restrict certain kinds of entities to certain parts of expressions:
The name of a field, parameter, or local variable may be used as an expression (15.14.1).
The name of a method may appear in an expression only as part of a method invocation expression (15.12).
The name of a class or interface may appear in an expression only as part of a class literal (15.8.2), a qualified
this
expression (15.8.4), a class instance creation expression (15.9), an array creation expression (15.10.1), a cast expression (15.16), aninstanceof
expression (15.20.2), an enum constant (8.9), or as part of a qualified name for a field or method.The name of a package may appear in an expression only as part of a qualified name for a class or interface.
Chapter 8: Classes
Class declarations define new reference types and describe how they are implemented (8.1).
A top level class is a class that is not a nested class.
A nested class is any class whose declaration occurs within the body of another class or interface.
This chapter discusses the common semantics of all classes - top level (7.6) and nested (including member classes (8.5, 9.5), local classes (14.3) and anonymous classes (15.9.5)). Details that are specific to particular kinds of classes are discussed in the sections dedicated to these constructs.
A named class may be declared abstract
(8.1.1.1) and must be declared abstract if it is incompletely implemented; such a class cannot be instantiated, but can be extended by subclasses.
The degree to which a class can be extended can be explicitly controlled (8.1.1.2). A class may be declared sealed
, in which case there is a fixed set of classes that directly extend the sealed
class. A class may be declared final
, in which case it cannot have any subclasses.
If a class is declared public
, then it can be referred to from code in any package of its module and potentially from code in other modules. Each class except Object
is an extension of (that is, a subclass of) a single existing class (8.1.4) and may implement interfaces (8.1.5). Classes may be generic (8.1.2), that is, they may declare type variables whose bindings may differ among different instances of the class.
Classes may be decorated with annotations (9.7) just like any other kind of declaration.
The body of a class declares members (fields and methods and nested classes and interfaces), instance and static initializers, and constructors (8.1.6 8.1.7). The scope (6.3) of a member (8.2) is the entire body of the declaration of the class to which the member belongs. Field, method, member class, member interface, and constructor declarations may include the access modifiers (6.6) public
, protected
, or private
. The members of a class include both declared and inherited members (8.2). Newly declared fields can hide fields declared in a superclass or superinterface. Newly declared class members and interface members can hide class or interface members declared in a superclass or superinterface. Newly declared methods can hide, implement, or override methods declared in a superclass or superinterface.
Field declarations (8.3) describe class variables, which are incarnated once, and instance variables, which are freshly incarnated for each instance of the class. A field may be declared final
(8.3.1.2), in which case it can be assigned to only once. Any field declaration may include an initializer.
Member class declarations (8.5) describe nested classes that are members of the surrounding class. Member classes may be static
, in which case they have no access to the instance variables of the surrounding class; or they may be inner classes (8.1.3).
Member interface declarations (8.5) describe nested interfaces that are members of the surrounding class.
Method declarations (8.4) describe code that may be invoked by method invocation expressions (15.12). A class method is invoked relative to the class type; an instance method is invoked with respect to some particular object that is an instance of a class type. A method whose declaration does not indicate how it is implemented must be declared abstract
. A method may be declared final
(8.4.3.3), in which case it cannot be hidden or overridden. A method may be implemented by platform-dependent native
code (8.4.3.4). A synchronized
method (8.4.3.6) automatically locks an object before executing its body and automatically unlocks the object on return, as if by use of a synchronized
statement (14.19), thus allowing its activities to be synchronized with those of other threads (17).
Method names may be overloaded (8.4.9).
Instance initializers (8.6) are blocks of executable code that may be used to help initialize an instance when it is created (15.9).
Static initializers (8.7) are blocks of executable code that may be used to help initialize a class.
Constructors (8.8) are similar to methods, but cannot be invoked directly by a method call; they are used to initialize new class instances. Like methods, they may be overloaded (8.8.8).
8.1 Class Declarations
A class declaration specifies a new class.
There are two kinds of class declarations: normal class declarations and enum declarations.
- ClassDeclaration:
- NormalClassDeclaration
- EnumDeclaration
- NormalClassDeclaration:
- {ClassModifier}
class
TypeIdentifier [TypeParameters]
[ClassExtends] [ClassImplements] [ClassPermits]
ClassBody
A class is also implicitly declared by a ClassInstanceCreationExpression (15.9.5) or EnumConstant (8.9.1) that ends with a class body.
The TypeIdentifier in a class declaration specifies the name of the class.
It is a compile-time error if a class has the same simple name as any of its enclosing classes or interfaces.
The scope and shadowing of a class declaration is specified in 6.3 and 6.4.
8.1.1 Class Modifiers
A class declaration may include class modifiers.
- ClassModifier:
- (one of)
- Annotation
public
protected
private
abstract
static
sealed
non-sealed
final
strictfp
The rules for annotation modifiers on a class declaration are specified in 9.7.4 and 9.7.5.
The access modifier public
(6.6) pertains only to top level classes (7.6) and member classes (8.5, 9.5).
The modifiers protected
, private
, and static
pertain only to member classes.
It is a compile-time error if the same keyword appears more than once as a modifier for a class declaration, or if a class declaration has more than one of the access modifiers public
, protected
, and private
(6.6).
It is a compile-time error if a class declaration has more than one of the class modifiers sealed
, non-sealed
and final
.
If two or more (distinct) class modifiers appear in a class declaration, then it is customary, though not required, that they appear in the order consistent with that shown above in the production for ClassModifier.
8.1.1.2 sealed
and final
Classes
Extensibility of class hierarchies is an important feature of object-oriented programming. However, there are circumstances where explicit control of this extensibility is desirable; in particular, when extensibility is being used not as a mechanism for code inheritance and reuse but, rather, as a way to list the kinds of values in a domain.
A class can be declared sealed
when a fixed non-empty set of direct subclasses is desired. A sealed
class permits a given set of direct subclasses (8.1.6).
A class can be declared final
if its definition is complete and no subclasses are desired or required.
It is a compile-time error if the name of a final
class appears in the extends
clause (8.1.4) of another class declaration; this implies that a final
class cannot have any subclasses.
This rule already appears in 8.1.4.
It is a compile-time error if a class is declared both final
and abstract
, because the implementation of such a class could never be completed (8.1.1.1).
Because a final
class never has any subclasses, the methods of a final
class are never overridden (8.4.8.1).
A class that is neither sealed
nor final
is freely extensible. Most classes are freely extensible by default. A class that directly extends a sealed
class (8.1.4) or directly implements a sealed
interface (8.1.5) is freely extensible only if it is declared non-sealed
.
It is a compile-time error if a class has a sealed
direct superclass or a sealed
direct superinterface and is not declared final
, sealed
, or non-sealed
.
An enum type can implement a
sealed
interface, as an enum type is (implicitly) eitherfinal
orsealed
(8.9).
JEP 395 proposes supporting Record classes in the Java programming language. A record class is implicitly final
, so can implement a sealed
interface.
It is a compile-time error if a class has neither a sealed
direct superclass nor a sealed
direct superinterface but is declared non-sealed
.
An effect of the
sealed
keyword is to force all direct subclasses to explicitly declare whether they arefinal
,sealed
, ornon-sealed
. This avoids accidentally exposing asealed
class hierarchy to unwanted subclassing.
8.1.4 Superclasses
The optional extends
clause in a normal class declaration specifies the direct superclass type of the current class.
- ClassExtends:
extends
ClassType
The extends
clause must not appear in the definition of the class Object
, or a compile-time error occurs, because it is the primordial class and has no direct superclass type.
The ClassType must name an accessible class type (6.6), or a compile-time error occurs.
It is a compile-time error if the ClassType names a class that is sealed
(8.1.1.2) and the current class is not a permitted direct subclass of that sealed
class (8.1.6).
It is a compile-time error if the ClassType names a class that is final
, because final
classes are not allowed to have subclasses (8.1.1.2).
It is a compile-time error if the ClassType names the class Enum
, which can only be extended by an enum class (8.9).
If the ClassType has type arguments, it must denote a well-formed parameterized type (4.5), and none of the type arguments may be wildcard type arguments, or a compile-time error occurs.
The direct superclass type of a class whose declaration lacks an extends
clause is as follows:
The class
Object
has no direct superclass type.For a class other than
Object
with a normal class declaration, the direct superclass type isObject
.For an enum class E, the direct superclass type is
Enum<
E>
.For an anonymous class, the direct superclass type is defined in 15.9.5.
The direct superclass of a class is the class named by its direct superclass type. The direct superclass is the class from whose implementation the implementation of the current class is derived.
The superclass relationship is the transitive closure of the direct superclass relationship. A class A is a superclass of class C if either of the following is true:
A is the direct superclass of C
Where a class B is the direct superclass of C, A is a superclass of B, applying this definition recursively.
A class is said to be a direct subclass of its direct superclass, and a subclass of each of its superclasses.
Example 8.1.4-1. Direct Superclasses and Subclasses
class Point { int x, y; }
final class ColoredPoint extends Point { int color; }
class Colored3DPoint extends ColoredPoint { int z; } // error
Here, the relationships are as follows:
The class
Point
is a direct subclass ofObject
.The class
Object
is the direct superclass of the classPoint
.The class
ColoredPoint
is a direct subclass of classPoint
.The class
Point
is the direct superclass of classColoredPoint
.
The declaration of class Colored3dPoint
causes a compile-time error because it attempts to extend the final class ColoredPoint
.
Example 8.1.4-2. Superclasses and Subclasses
class Point { int x, y; }
class ColoredPoint extends Point { int color; }
final class Colored3dPoint extends ColoredPoint { int z; }
Here, the relationships are as follows:
The class
Point
is a superclass of classColoredPoint
.The class
Point
is a superclass of classColored3dPoint
.The class
ColoredPoint
is a subclass of classPoint
.The class
ColoredPoint
is a superclass of classColored3dPoint
.The class
Colored3dPoint
is a subclass of classColoredPoint
.The class
Colored3dPoint
is a subclass of classPoint
.
A class C directly depends on a class or interface A if A is mentioned in the extends
or implements
clause of C either as a superclass or superinterface, or as a qualifier in the fully qualified form of a superclass or superinterface name.
A class C depends on a class or interface A if any of the following is true:
C directly depends on A.
C directly depends on an interface I that depends (9.1.3) on A*.
C directly depends on a class D that depends on A (using this definition recursively).
It is a compile-time error if a class depends on itself.
If circularly declared classes are detected at run time, as classes are loaded, then a ClassCircularityError
is thrown (12.2.1).
Example 8.1.4-3. Class Depends on Itself
class Point extends ColoredPoint { int x, y; }
class ColoredPoint extends Point { int color; }
This program causes a compile-time error because class Point
depends on itself.
8.1.5 Superinterfaces
The optional implements
clause in a class declaration lists interface types that are the direct superinterface types of the class being declared.
- ClassImplements:
implements
InterfaceTypeList- InterfaceTypeList:
- InterfaceType {
,
InterfaceType}
Each InterfaceType must name an accessible interface type (6.6), or a compile-time error occurs.
It is a compile-time error if an InterfaceType names an interface that is sealed
(9.1.1.4) and the class being declared is not a permitted direct subclass of the named interface (9.1.4).
If an InterfaceType has type arguments, it must denote a well-formed parameterized type (4.5), and none of the type arguments may be wildcard type arguments, or a compile-time error occurs.
It is a compile-time error if the same interface is named by a direct superinterface more than once in a single implements
clause. This is true even if the interface is named in different ways.
Example 8.1.5-1. Illegal Superinterfaces
class Redundant implements java.lang.Cloneable, Cloneable {
int x;
}
This program results in a compile-time error because the names java.lang.Cloneable
and Cloneable
refer to the same interface.
A class whose declaration lacks an implements
clause has no direct superinterface types, with one exception: an anonymous class may have a superinterface type, as defined in 15.9.5.
An interface is a direct superinterface of a class if the interface is named by one of the direct superinterface types of the class.*
An interface I is a superinterface of class C if any of the following is true:
I is a direct superinterface of C.
C has some direct superinterface J for which I is a superinterface, using the definition of "superinterface of an interface" given in 9.1.3.
I is a superinterface of the direct superclass of C.
A class can have a superinterface in more than one way.
A class is said to directly implement its direct superinterfaces, and to implement all of its superinterfaces. We also say that a class is a direct subclass of its direct superinterfaces, and a subclass of all of its superinterfaces.
A class may not declare a direct superclass type and a direct superinterface type, or two direct superinterface types, which are, or which have supertypes (4.10.2) which are, different parameterizations of the same generic interface (9.1.2), or a parameterization of a generic interface and a raw type naming that same generic interface. In the case of such a conflict, a compile-time error occurs.
This requirement was introduced in order to support translation by type erasure (4.6).
Example 8.1.5-2. Superinterfaces
interface Colorable {
void setColor(int color);
int getColor();
}
enum Finish { MATTE, GLOSSY }
interface Paintable extends Colorable {
void setFinish(Finish finish);
Finish getFinish();
}
class Point { int x, y; }
class ColoredPoint extends Point implements Colorable {
int color;
public void setColor(int color) { this.color = color; }
public int getColor() { return color; }
}
class PaintedPoint extends ColoredPoint implements Paintable {
Finish finish;
public void setFinish(Finish finish) {
this.finish = finish;
}
public Finish getFinish() { return finish; }
}
Here, the relationships are as follows:
The interface
Paintable
is a superinterface of classPaintedPoint
.The interface
Colorable
is a superinterface of classColoredPoint
and of classPaintedPoint
.The interface
Paintable
is a subinterface of the interfaceColorable
, andColorable
is a superinterface ofPaintable
, as defined in 9.1.3.
The class PaintedPoint
has Colorable
as a superinterface both because it is a superinterface of ColoredPoint
and because it is a superinterface of Paintable
.
Example 8.1.5-3. Illegal Multiple Inheritance of an Interface
interface I<T> {}
class B implements I<Integer> {}
class C extends B implements I<String> {}
Class C
causes a compile-time error because it attempts to be a subtype of both I<Integer
> and I<String
>.
...
8.1.6 Permitted Direct Subclasses
This is a new subsection. The existing subsection 8.1.6 "Class Body and Member Declarations" is renumbered to 8.1.7, and all existing references to it must be renumbered.
The optional permits
clause in a class declaration specifies the classes that are permitted to directly extend a sealed
class (8.1.1.2).
- ClassPermits
permits
TypeName {,
TypeName }
It is a compile-time error if a class declaration has a permits
clause but the declared class is not sealed
.
Every TypeName in the permits
clause of a class declaration must denote an accessible class (6.6); otherwise a compile-time error occurs.
It is a compile-time error if the same class is specified more than once in a permits
clause. This is true even if the class is named in different ways.
The canonical name of a class does not need to be used in a
permits
clause, but apermits
clause can only name a class once. For example, the following program fails to compile:package p; sealed class A permits B, C, p.B {} // Error! non-sealed class B extends A {}
non-sealed class C extends A {}
It is a compile-time error if the declaration of a class C names a class in its permits
clause, but C is not the direct superclass (8.1.4) of the named class.
If a sealed
class C belongs to a named module, then every class named in the permits
clause of the declaration of C must belong to the same module as C; otherwise a compile-time error occurs.
If a sealed
class C belongs to an unnamed module, then every class named in the permits
clause of the declaration of C must belong to the same package as C; otherwise a compile-time error occurs.
Sealed class hierarchies are not intended to be declared across different maintenance domains. Modules cannot depend on each other in a circular fashion, yet a
sealed
class and its direct subclasses need to refer to each other in a circular fashion (inpermits
andextends
clauses, respectively). Necessarily, therefore, asealed
class and its direct subclasses must co-exist in the same module. In an unnamed module, asealed
class and its direct subclasses must belong to the same package.
The permitted direct subclasses of a sealed
class C are the classes listed by its permits
clause, or, if C lacks a permits
clause, each class declared in the same compilation unit as C (7.3) which has a canonical name (6.7) and whose direct superclass is C.
This means that if a
sealed
class C lacks apermits
clause one will be inferred that contains all the top-level and member classes in the same compilation unit that list C as their direct superclass. The requirement of having a canonical name means that no local classes or anonymous classes will be considered.
It is a compile-time error if the declaration of a sealed
class C lacks a permits
clause and has no permitted direct subclasses.
8.9 Enum Classes
An enum declaration specifies a new enum class, a special kind of class that defines a small set of named class instances.
- EnumDeclaration:
- {ClassModifier}
enum
TypeIdentifier [ClassImplements] EnumBody
An enum declaration may specify a top level enum class (7.6) or a member enum class (8.5, 9.5).
It is a compile-time error if an enum declaration has the modifier abstract
, or final
, sealed
or non-sealed
.
An enum declaration is implicitly final
unless it contains at least one enum constant that has a class body (8.9.1).
An enum declaration is either implicitly final
or implicitly sealed
, as follows:
An enum declaration is implicitly
final
if it contains no enum constants that have a class body (8.9.1).An enum declaration is implicitly
sealed
if it contains at least one enum constant that has a class body. The permitted direct subclasses (8.1.6) are the anonymous classes implicitly declared by the enum constants that have a class body.
A member enum class is implicitly static
. It is permitted for the declaration of a member enum class to redundantly specify the static
modifier.
This implies that it is impossible to declare an enum class as a member of an inner class (8.1.3), because an inner class cannot have
static
members except for constant variables.
It is a compile-time error if the same keyword appears more than once as a modifier for an enum declaration, or if an enum declaration has more than one of the access modifiers public
, protected
, and private
(6.6).
An enum declaration does not have an extends
clause. The direct superclass type of an enum class E is Enum<
E>
(8.1.4).
An enum class has no instances other than those defined by its enum constants. It is a compile-time error to attempt to explicitly instantiate an enum class (15.9.1).
In addition to the compile-time error, three further mechanisms ensure that no instances of an enum class exist beyond those defined by its enum constants:
The
final
clone
method inEnum
ensures that enum constants can never be cloned.Reflective instantiation of enum classes is prohibited.
Special treatment by the serialization mechanism ensures that duplicate instances are never created as a result of deserialization.
8.9.1 Enum Constants
The body of an enum declaration may contain enum constants. An enum constant defines an instance of the enum class.
- EnumBody:
{
[EnumConstantList] [,
] [EnumBodyDeclarations]}
- EnumConstantList:
- EnumConstant {
,
EnumConstant} - EnumConstant:
- {EnumConstantModifier} Identifier [
(
[ArgumentList])
] [ClassBody] - EnumConstantModifier:
- Annotation
The following production from 15.12 is shown here for convenience:
- ArgumentList:
- Expression {
,
Expression}
The rules for annotation modifiers on an enum constant declaration are specified in 9.7.4 and 9.7.5.
The Identifier in a EnumConstant may be used in a name to refer to the enum constant.
The scope and shadowing of an enum constant is specified in 6.3 and 6.4.
An enum constant may be followed by arguments, which are passed to the constructor of the enum when the constant is created during class initialization as described later in this section. The constructor to be invoked is chosen using the normal rules of overload resolution (15.12.2). If the arguments are omitted, an empty argument list is assumed.
The optional class body of an enum constant implicitly defines an anonymous class declaration (15.9.5) that extends the immediately enclosing enum type. The optional class body of an enum constant implicitly defines an anonymous class (15.9.5) that (i) is final
, and (ii) extends the immediately enclosing sealed
enum class. The class body is governed by the usual rules of anonymous classes; in particular it cannot contain any constructors. Instance methods declared in these class bodies may be invoked outside the enclosing enum class only if they override accessible methods in the enclosing enum class (8.4.8).
Because there is only one instance of each enum constant, it is permitted to use the ==
operator in place of the equals
method when comparing two object references if it is known that at least one of them refers to an enum constant.
The
equals
method inEnum
is afinal
method that merely invokessuper.equals
on its argument and returns the result, thus performing an identity comparison.
Chapter 9: Interfaces
An interface declaration introduces a new interface that can be implemented by one or more classes. Programs can use interfaces to provide a common supertype for otherwise-unrelated classes.
Interfaces have no instance variables, and typically declare one or more abstract
methods; otherwise unrelated classes can implement an interface by providing implementations for its abstract
methods. Interfaces may not be directly instantiated.
A top level interface (7.6) is an interface that is declared at the top level of a compilation unit.
A nested interface is any interface whose declaration occurs as a member interface (8.5, 9.5) of another class or interface.
An annotation interface (9.6) is an interface declared with special syntax, intended to be implemented by reflective representations of annotations (9.7).
This chapter discusses the common semantics of all interfaces. Details that are specific to particular kinds of interfaces are discussed in the sections dedicated to these constructs.
An interface may be declared to be a direct extension of one or more other interfaces, meaning that it inherits all the member classes and interfaces, instance methods, and static
fields 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 (8.1.5), 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 a superclass.
Unlike a class, an interface cannot be declared final
. However, an interface may be declared sealed
(9.1.1.4), when there is a fixed set of classes and interfaces that may directly implement or extend the sealed
interface.
A variable whose declared type is an interface type may have as its value a reference to any instance of a class which implements the specified interface. It is not sufficient that the class happen to implement all the abstract
methods of the interface; the class or one of its superclasses must actually be declared to implement the interface, or else the class is not considered to implement the interface.
9.1 Interface Declarations
An interface declaration specifies an interface. There are two kinds of interface declarations - normal interface declarations and annotation interface declarations (9.6).
- InterfaceDeclaration:
- NormalInterfaceDeclaration
- AnnotationTypeDeclaration
- NormalInterfaceDeclaration:
- {InterfaceModifier}
interface
TypeIdentifier [TypeParameters]
[InterfaceExtends] [InterfacePermits]
InterfaceBody
The TypeIdentifier in an interface declaration specifies the name of the interface.
It is a compile-time error if an interface has the same simple name as any of its enclosing classes or interfaces.
The scope and shadowing of an interface declaration is specified in 6.3 and 6.4.
9.1.1 Interface Modifiers
An interface declaration may include interface modifiers.
- InterfaceModifier:
- (one of)
- Annotation
public
protected
private
abstract
static
sealed
non-sealed
strictfp
The rules for annotation modifiers on an interface declaration are specified in 9.7.4 and 9.7.5.
The modifiers protected
, private
, and static
pertain only to member interfaces (8.5, 9.5).
It is a compile-time error if the same keyword appears more than once as a modifier for an interface declaration, or if a interface declaration has more than one of the access modifiers public
, protected
, and private
(6.6).
It is a compile-time error if an interface is declared both sealed
and non-sealed
.
If two or more (distinct) interface modifiers appear in an interface declaration, then it is customary, though not required, that they appear in the order consistent with that shown above in the production for InterfaceModifier.
9.1.1.4 sealed
Interfaces
An interface can be declared sealed
when there is a known, non-empty, fixed set of direct subclasses and subinterfaces, and no further direct subclasses or subinterfaces are desired or required. A sealed
interface permits a given set of direct subclasses and subinterfaces (9.1.4).
An interface that is not sealed
is freely extensible. Most interfaces are freely extensible by default. An interface that directly extends a sealed
interface (9.1.3) is freely extensible only if it is declared non-sealed
.
It is a compile-time error if an interface has a sealed
direct superinterface and is not declared sealed
or non-sealed
.
It is a compile-time error if an interface has no sealed
direct superinterface but is declared non-sealed
.
9.1.3 Superinterfaces
If an extends
clause is provided, then the interface being declared extends each of the listed interface types and therefore inherits the member classes and interfaces, instance methods, and constants of each of the listed interface types.
These listed interface types are the direct superinterface types of the interface being declared.
- InterfaceExtends:
extends
InterfaceTypeList
The following production from 8.1.5 is shown here for convenience:
- InterfaceTypeList:
- InterfaceType {
,
InterfaceType}
Each InterfaceType in the extends
clause of an interface declaration must name an accessible interface type (6.6), or a compile-time error occurs.
It is a compile-time error if an InterfaceType names an interface that is sealed
(9.1.1.4) and the current interface is not a permitted direct subinterface of that sealed
interface (9.1.4).
If an InterfaceType has type arguments, it must denote a well-formed parameterized type (4.5), and none of the type arguments may be wildcard type arguments, or a compile-time error occurs.
The direct superinterface type of an annotation interface is, implicitly, java.lang.annotation.Annotation
.
One interface is a direct superinterface of another interface if the first interface is named by one of the direct superinterface types of the second interface.
The superinterface relationship is the transitive closure of the direct superinterface relationship. An interface K is a superinterface of interface I if either of the following is true:
K is a direct superinterface of I.
Where J is a direct superinterface of I, K is a superinterface of J, applying this definition recursively.
An interface is said to be a direct subinterface of its direct superinterface, and a subinterface of each of its superinterfaces.
While every class is an extension of class Object
, there is no single interface of which all interfaces are extensions.
An interface I directly depends on a class or interface A if A is mentioned in the extends
clause of I either as a superinterface or as a qualifier in the fully qualified form of a superinterface name.
An interface I depends on a class or interface A if any of the following is true:
I directly depends on A.
I directly depends on a class C that depends on A (8.1.5).
I directly depends on an interface J that depends on A (using this definition recursively).
It is a compile-time error if an interface depends on itself.
If circularly declared interfaces are detected at run time, as interfaces are loaded, then a ClassCircularityError
is thrown (12.2.1).
9.1.4 Permitted Direct Subclasses and Subinterfaces
This is a new subsection. The existing subsection 9.1.4 "Interface Body and Member Declarations" is renumbered to 9.1.5, and all existing references to it must be renumbered.
The optional permits
clause in an interface declaration lists the classes and interfaces that are permitted to directly implement or extend a sealed
interface (9.1.1.4).
- InterfacePermits
permits
TypeName {,
TypeName }
It is a compile-time error if an interface declaration has a permits
clause but the declared interface is not sealed
.
Every TypeName in the permits
clause of an interface declaration must denote an accessible class or interface (6.6); otherwise a compile-time error occurs.
It is a compile-time error if a class or interface is named more than once in a single permits
clause. This is true even if the class or interface is named in different ways.
The canonical name of a class or interface does not need to be used in a
permits
clause, but apermits
clause can only name a class or interface once. For example, the following program fails to compile:package p; sealed interface I permits C, D, p.C {} // Error! non-sealed class C implements I {} non-sealed class D implements I {}
It is a compile-time error if the declaration of an interface I names a class or interface in its permits
clause, but I is not a direct superinterface (8.1.5, 9.1.3) of the named class or interface.
If a sealed
interface I belongs to a named module, then every class or interface named in the permits
clause of the declaration of I must belong to the same module as I; otherwise a compile-time error occurs.
If a sealed
interface I belongs to an unnamed module, then every class or interface named in the permits
clause of the declaration of I must belong to the same package as I; otherwise a compile-time error occurs.
Sealed interface hierarchies are not intended to be declared across different maintenance domains. Modules cannot depend on each other in a circular fashion, yet a
sealed
interface and its direct subclasses and subinterfaces need to refer to each other in a circular fashion (inpermits
,implements
andextends
clauses, respectively). Necessarily, therefore, asealed
interface and its direct subclasses and subinterfaces must co-exist in the same module. In an unnamed module, asealed
interface and its direct subclasses and subinterfaces must belong to the same package.
The permitted direct subclasses and subinterfaces of a sealed
interface I are the classes and interfaces listed by its permits
clause, or, if I lacks a permits
clause, each top level or member class or interface declared in the same compilation unit as I (7.3) which has a canonical name (6.7) and whose direct superinterfaces include I.
It is a compile-time error if the declaration of a sealed
interface I lacks a permits
clause and has no permitted direct subclasses or subinterfaces.
9.6 Annotation Interfaces
An annotation declaration specifies a new annotation interface, a special kind of interface. To distinguish an annotation declaration from a normal interface declaration, the keyword interface
is preceded by an at sign (@
).
- AnnotationDeclaration:
- {InterfaceModifier}
@
interface
TypeIdentifier AnnotationInterfaceBody
Note that the at sign (
@
) and the keywordinterface
are distinct tokens. It is possible to separate them with whitespace, but this is discouraged as a matter of style.
It is a compile-time error if an annotation declaration has the modifier sealed
(9.1.1.4).
The rules for annotation modifiers on an annotation declaration are specified in 9.7.4 and 9.7.5.
The TypeIdentifier in an annotation declaration specifies the name of the annotation interface.
It is a compile-time error if an annotation interface has the same simple name as any of its enclosing classes or interfaces.
The direct superinterface of every annotation interface is java.lang.annotation.Annotation
(9.1.3).
By virtue of the AnnotationInterfaceDeclaration syntax, an annotation interface declaration cannot be generic, and no
extends
clause is permitted.
A consequence of the fact that an annotation interface cannot explicitly declare a superclass type or superinterface type is that a subinterface of an annotation interface is never itself an annotation interface. Similarly,
java.lang.annotation.Annotation
is not itself an annotation interface.
An annotation interface inherits several members from java.lang.annotation.Annotation
, including the implicitly declared methods corresponding to the instance methods of Object
, yet these methods do not define elements of the annotation interface (9.6.1).
Because these methods do not define elements of the annotation interface, it is illegal to use them in annotations of that type (9.7). Without this rule, we could not ensure that elements were of the types representable in annotations, or that accessor methods for them would be available.
Unless explicitly modified herein, all of the rules that apply to normal interface declarations apply to annotation declarations.
For example, annotation interfaces share the same namespace as normal classes and interfaces; and annotation declarations have the same scope and accessibility as interface declarations.
9.8 Functional Interfaces
A functional interface is an interface that is not declared sealed
that has just one abstract method (aside from the methods of Object
), and thus represents a single function contract. This "single" method may take the form of multiple abstract methods with override-equivalent signatures inherited from superinterfaces; in this case, the inherited methods logically represent a single method.
For an interface I that is not declared sealed
, let M be the set of abstract
methods that are members of I that do not have the same signature as any public
instance method of the class Object
(4.3.2). Then, I is a functional interface if there exists a method m in M for which both of the following are true:
The signature of m is a subsignature (8.4.2) of every method's signature in M.
m is return-type-substitutable (8.4.5) for every method in M.
In addition to the usual process of creating an interface instance by declaring and instantiating a class (15.9), instances of functional interfaces can be created with method reference expressions and lambda expressions (15.13, 15.27).
The definition of functional interface excludes methods in an interface that are also
public
methods inObject
. This is to allow functional treatment of an interface likejava.util.Comparator<T>
that declares multipleabstract
methods of which only one is really "new" -int compare(T,T)
. The other -boolean equals(Object)
- is an explicit declaration of anabstract
method that would otherwise be implicitly declared in the interface (9.2) and automatically implemented by every class thatimplements
the interface.
Note that if non-
public
methods ofObject
, such asclone()
, are explicitly declared in an interface aspublic
, they are not automatically implemented by every class thatimplements
the interface. The implementation inherited fromObject
isprotected
while the interface method ispublic
, so the only way to implement the interface would be for a class to override the non-public
Object
method with apublic
method.
Example 9.8-1. Functional Interfaces
A simple example of a functional interface is:
interface Runnable {
void run();
}
The following interface is not functional because it declares nothing which is not already a member of Object
:
interface NonFunc {
boolean equals(Object obj);
}
However, its subinterface can be functional by declaring an abstract
method which is not a member of Object
:
interface Func extends NonFunc {
int compare(String o1, String o2);
}
Similarly, the well known interface java.util.Comparator<T>
is functional because it has one abstract
non-Object
method:
interface Comparator<T> {
boolean equals(Object obj);
int compare(T o1, T o2);
}
The following interface is not functional because while it only declares one abstract
method which is not a member of Object
, it declares two abstract
methods which are not public
members of Object
:
interface Foo {
int m();
Object clone();
}
Example 9.8-2. Functional Interfaces and Erasure
In the following interface hierarchy, Z
is a functional interface because while it inherits two abstract
methods which are not members of Object
, they have the same signature, so the inherited methods logically represent a single method:
interface X { int m(Iterable<String> arg); }
interface Y { int m(Iterable<String> arg); }
interface Z extends X, Y {}
Similarly, Z
is a functional interface in the following interface hierarchy because Y.m
is a subsignature of X.m
and is return-type-substitutable for X.m
:
interface X { Iterable m(Iterable<String> arg); }
interface Y { Iterable<String> m(Iterable arg); }
interface Z extends X, Y {}
The definition of functional interface respects the fact that an interface cannot have two members which are not subsignatures of each other, yet have the same erasure (9.4.1.2). Thus, in the following three interface hierarchies where Z
causes a compile-time error, Z
is not a functional interface: (because none of its abstract
members are subsignatures of all other abstract
members)
interface X { int m(Iterable<String> arg); }
interface Y { int m(Iterable<Integer> arg); }
interface Z extends X, Y {}
interface X { int m(Iterable<String> arg, Class c); }
interface Y { int m(Iterable arg, Class<?> c); }
interface Z extends X, Y {}
interface X<T> { void m(T arg); }
interface Y<T> { void m(T arg); }
interface Z<A, B> extends X<A>, Y<B> {}
Similarly, the definition of "functional interface" respects the fact that an interface may only have methods with override-equivalent signatures if one is return-type-substitutable for all the others. Thus, in the following interface hierarchy where Z
causes a compile-time error, Z
is not a functional interface: (because none of its abstract
members are return-type-substitutable for all other abstract
members)
interface X { long m(); }
interface Y { int m(); }
interface Z extends X, Y {}
In the following example, the declarations of Foo<T,N>
and Bar
are legal: in each, the methods called m
are not subsignatures of each other, but do have different erasures. Still, the fact that the methods in each are not subsignatures means Foo<T,N>
and Bar
are not functional interfaces. However, Baz
is a functional interface because the methods it inherits from Foo<Integer,Integer>
have the same signature and so logically represent a single method.
interface Foo<T, N extends Number> {
void m(T arg);
void m(N arg);
}
interface Bar extends Foo<String, Integer> {}
interface Baz extends Foo<Integer, Integer> {}
Finally, the following examples demonstrate the same rules as above, but with generic methods:
interface Exec { <T> T execute(Action<T> a); }
// Functional
interface X { <T> T execute(Action<T> a); }
interface Y { <S> S execute(Action<S> a); }
interface Exec extends X, Y {}
// Functional: signatures are logically "the same"
interface X { <T> T execute(Action<T> a); }
interface Y { <S,T> S execute(Action<S> a); }
interface Exec extends X, Y {}
// Error: different signatures, same erasure
Example 9.8-3. Generic Functional Interfaces
Functional interfaces can be generic, such as java.util.function.Predicate<T>
. Such a functional interface may be parameterized in a way that produces distinct abstract
methods - that is, multiple methods that cannot be legally overridden with a single declaration. For example:
interface I { Object m(Class c); }
interface J<S> { S m(Class<?> c); }
interface K<T> { T m(Class<?> c); }
interface Functional<S,T> extends I, J<S>, K<T> {}
Functional<S,T>
is a functional interface - I.m
is return-type-substitutable for J.m
and K.m
- but the functional interface type Functional<String,Integer>
clearly cannot be implemented with a single method. However, other parameterizations of Functional<S,T>
which are functional interface types are possible.
The declaration of a functional interface allows a functional interface type to be used in a program. There are four kinds of functional interface type:
The type of a non-generic (6.1) functional interface
A parameterized type that is a parameterization (4.5) of a generic functional interface
The raw type (4.8) of a generic functional interface
An intersection type (4.9) that induces a notional functional interface
In special circumstances, it is useful to treat an intersection type as a functional interface type. Typically, this will look like an intersection of a functional interface type with one or more marker interface types, such as
Runnable & java.io.Serializable
. Such an intersection can be used in casts (15.16) that force a lambda expression to conform to a certain type. If one of the interface types in the intersection isjava.io.Serializable
, special run-time support for serialization is triggered (15.27.4).
Chapter 13: Binary Compatibility
13.4 Evolution of Classes
13.4.2 sealed
, non-sealed
and final
Classes
The discussion about final
classes has been moved to a new subsection 13.4.2.3.
13.4.2.1 sealed
Classes
If a class that was freely extensible (8.1.1.2) is changed to be declared sealed
, then an IncompatibleClassChangeError
is thrown if a binary of a pre-existing subclass of this class is loaded that is not contained in its permits
clause; such a change is not recommended for widely distributed classes.
Changing a class that was declared final
to be declared sealed
does not break compatibility with pre-existing binaries.
Removing the sealed
modifier from a class that does not have a sealed
direct superclass or a sealed
direct superinterface does not break compatibility with pre-existing binaries.
If a
sealed
class C did have asealed
direct superclass or asealed
direct superinterface, then simply removing thesealed
modifier would mean that C would not compile as every class with asealed
direct superclass or asealed
direct superinterface must be eitherfinal
,sealed
ornon-sealed
(8.1.1.2).
13.4.2.2 non-sealed
Classes
Changing a class that was declared sealed
to be declared non-sealed
does not break compatibility with pre-existing binaries.
Changing a class that was declared final
to be declared non-sealed
does not break compatibility with pre-existing binaries.
A
non-sealed
class C must have asealed
direct superclass or asealed
direct superinterface (8.1.1.2). Simply removing thenon-sealed
modifier from C would mean that C would not compile as every class with asealed
direct superclass or asealed
direct superinterface must be eitherfinal
,sealed
ornon-sealed
(8.1.1.2).
13.4.2.3 final
Classes
If a class that was not declared final
is changed to be declared final
, then a VerifyError
is thrown if a binary of a pre-existing subclass of this class is loaded, because final
classes can have no subclasses; such a change is not recommended for widely distributed classes.
Changing a class that is declared final
to no longer be declared final
does not break compatibility with pre-existing binaries.
Removing the final
modifier from a class that does not have a sealed
direct superclass or a sealed
direct superinterface does not break compatibility with pre-existing binaries.
If a
final
class C did have asealed
direct superclass or asealed
direct superinterface, then simply removing thefinal
modifier would mean that C would not compile as every class with asealed
direct superclass or asealed
direct superinterface must be eitherfinal
,sealed
ornon-sealed
(8.1.1.2).
13.4.5 Permitted Direct Subclasses
Adding a class to the set of permitted direct subclasses of a sealed
class (8.1.6) will not break compatibility with pre-existing binaries.
If a class is removed from the set of permitted direct subclasses of a sealed
class (8.1.6) then an IncompatibleClassChangeError
is thrown if the pre-existing binary of the removed class is loaded.
13.5 Evolution of Interfaces
Existing section 13.5.2 is renumbered as 13.5.3. Existing sections 13.5.3 - 13.5.7 are renumbered as 13.5.5 - 13.5.9.
13.5.2 sealed
and non-sealed
Interfaces
If an interface that was freely extensible (9.1.1.4) is changed to be declared sealed
, then an IncompatibleClassChangeError
is thrown if a binary of a pre-existing subclass or subinterface of this interface is loaded that is not contained in its permits
clause; such a change is not recommended for widely distributed classes.
Removing the sealed
modifier from an interface that does not have a sealed
direct superinterface does not break compatibility with pre-existing binaries.
If a
sealed
interface I did have asealed
direct superinterface, then simply removing thesealed
modifier from I would mean that I would not compile as every interface with asealed
direct superinterface must besealed
ornon-sealed
(9.1.1.4).
Changing an interface that is declared sealed
to be declared non-sealed
does not break compatibility with pre-existing binaries.
A
non-sealed
interface I must have asealed
direct superinterface (9.1.1.4). Simply removing thenon-sealed
modifier from I would mean that I would not compile as every interface with asealed
direct superinterface must besealed
ornon-sealed
(9.1.1.4).
13.5.4 Permitted Direct Subclasses and Subinterfaces
Adding a class or interface to the set of permitted direct subclasses or subinterfaces, respectively, of a sealed
interface (9.1.4) will not break compatibility with pre-existing binaries.
If a class or interface is removed from the set of permitted direct subclasses or subinterfaces of a sealed
interface (9.1.4) then an IncompatibleClassChangeError
is thrown if the pre-existing binary of the removed class or interface is loaded.
Chapter 14: Blocks and Statements
14.3 Local Class and Interface Declarations
A local class or a local interface is a nested class or interface (8, 9) whose declaration is immediately contained by a block (14.2).
- LocalClassOrInterfaceDeclaration:
- ClassDeclaration
- NormalInterfaceDeclaration
A local class may be an enum class (8.9). A local interface may not be an annotation interface (9.6).
Local class and interface declarations may be intermixed freely with statements in the block.
A local class or interface is not a member of any package, class, or interface. Unlike an anonymous class (15.9.5), a local class or interface has a simple name (6.2, 6.7).
Local enum classes and local interfaces are implicitly static
(8.1.1.4, 9.1.1.3). A local class that is not implicitly static
is an inner class (8.1.3).
It is a compile-time error if a local class or interface is declared with any of the access modifiers public
, protected
, or private
(6.6), or the modifier any of the modifiers static
(8.1.1), sealed
or non-sealed
(8.1.1.2).
It is a compile-time error if the direct superclass or direct superinterface of a local class is sealed
(8.1.1.2).
It is a compile-time error if the direct superinterface of a local interface is sealed
(9.1.1.4).
The scope and shadowing of a local class or interface declaration is specified in 6.3 and 6.4.
Example 14.3-1. Local Class and Interface Declarations
Here is an example that illustrates several aspects of the rules given above:
class Global {
class Cyclic {}
void foo() {
new Cyclic(); // create a Global.Cyclic
class Cyclic extends Cyclic {} // circular definition
{
class Local {}
{
class Local {} // compile-time error
}
class Local {} // compile-time error
class AnotherLocal {
void bar() {
class Local {} // ok
}
}
}
class Local {} // ok, not in scope of prior Local
}
}
The first statement of method foo
creates an instance of the member class Global.Cyclic
rather than an instance of the local class Cyclic
, because the statement appears prior to the scope of the local class declaration.
The fact that the scope of a local class declaration encompasses its whole declaration (not only its body) means that the definition of the local class Cyclic
is indeed cyclic because it extends itself rather than Global.Cyclic
. Consequently, the declaration of the local class Cyclic
is rejected at compile time.
Since local class names cannot be redeclared within the same method (or constructor or initializer, as the case may be), the second and third declarations of Local
result in compile-time errors. However, Local
can be redeclared in the context of another, more deeply nested, class such as AnotherLocal
.
The final declaration of Local
is legal, since it occurs outside the scope of any prior declaration of Local
.
Chapter 15: Expressions
15.9 Class Instance Creation Expressions
15.9.1 Determining the Class being Instantiated
If ClassOrInterfaceTypeToInstantiate ends with TypeArguments (rather than <>
), then ClassOrInterfaceTypeToInstantiate must denote a well-formed parameterized type (4.5), or a compile-time error occurs.
If ClassOrInterfaceTypeToInstantiate ends with <>
, but the class or interface denoted by the Identifier in ClassOrInterfaceTypeToInstantiate is not generic, then a compile-time error occurs.
If the class instance creation expression ends in a class body, then the class being instantiated is an anonymous class. Then:
If the class instance creation expression is unqualified, then:
The Identifier in ClassOrInterfaceTypeToInstantiate must denote either a class that is accessible, non-
final
, non-sealed
, and not an enum class, or an interface that is accessible and non-sealed
(6.6). Otherwise a compile-time error occurs.If the Identifier in ClassOrInterfaceTypeToInstantiate denotes a class, C, then an anonymous direct subclass of C is declared. If TypeArguments is present, then C has type arguments given by TypeArguments; if
<>
is present, then C will have its type arguments inferred in 15.9.3; otherwise, C has no type arguments. The body of the subclass is the ClassBody given in the class instance creation expression. The class being instantiated is the anonymous subclass.If the Identifier in ClassOrInterfaceTypeToInstantiate denotes an interface, I, then an anonymous direct subclass of
Object
that implements I is declared. If TypeArguments is present, then I has type arguments given by TypeArguments; if<>
is present, then I will have its type arguments inferred in 15.9.3; otherwise, I has no type arguments. The body of the subclass is the ClassBody given in the class instance creation expression. The class being instantiated is the anonymous subclass.If the class instance creation expression is qualified, then:
The Identifier in ClassOrInterfaceTypeToInstantiate must unambiguously denote an inner class that is accessible, non-
final
, non-sealed
, not an enum class, and a member of the compile-time type of the Primary expression or the ExpressionName. Otherwise, a compile-time error occurs.Let the Identifier in ClassOrInterfaceTypeToInstantiate denote a class, C. An anonymous direct subclass of C is declared. If TypeArguments is present, then C has type arguments given by TypeArguments; if
<>
is present, then C will have its type arguments inferred in 15.9.3; otherwise, C has no type arguments. The body of the subclass is the ClassBody given in the class instance creation expression. The class being instantiated is the anonymous subclass.
If a class instance creation expression does not declare an anonymous class, then:
If the class instance creation expression is unqualified, then:
The Identifier in ClassOrInterfaceTypeToInstantiate must denote a class that is accessible, non-
abstract
, and not an enum class. Otherwise, a compile-time error occurs.The class being instantiated is specified by the Identifier in ClassOrInterfaceTypeToInstantiate. If TypeArguments is present, then the class has type arguments given by TypeArguments; if
<>
is present, then the class will have its type arguments inferred in 15.9.3; otherwise, the class has no type arguments.If the class instance creation expression is qualified, then:
The ClassOrInterfaceTypeToInstantiate must unambiguously denote an inner class that is accessible, non-
abstract
, not an enum class, and a member of the compile-time type of the Primary expression or the ExpressionName.The class being instantiated is specified by the Identifier in ClassOrInterfaceTypeToInstantiate. If TypeArguments is present, then the class has type arguments given by TypeArguments; if
<>
is present, then the class will have its type arguments inferred in 15.9.3; otherwise, the class has no type arguments.
15.9.5 Anonymous Class Declarations
An anonymous class is implicitly declared by a class instance creation expression or an enum constant (8.9.1) that ends with a class body.
An anonymous class is never abstract
(8.1.1.1).
An anonymous class declared by a class instance creation expression is never final
(8.1.1.2). An anonymous class declared by an enum constant is always final
.
An anonymous class is never sealed
(8.1.1.2), and thus has no permitted direct subclasses (8.1.6).
The treatment of
final
is relevant in casting, in particular the narrowing reference conversion allowed for the cast operator (5.5). It is not relevant to subclassing, because it is impossible to declare a subclass of an anonymous class, despite the anonymous class being non-final
, because an anonymous class cannot be named by anextends
clause (8.1.4).
An anonymous class is always an inner class (8.1.3).
The direct superclass type or direct superinterface type of an anonymous class declared by a class instance creation expression is given by the expression (15.9.1), with type arguments inferred as necessary while choosing a constructor (15.9.3). If a direct superinterface type is given, the direct superclass type is Object
.
The direct superclass type of an anonymous class declared by an enum constant is the type of the declaring enum class.
The ClassBody of the class instance creation expression or enum constant declares fields (8.3), methods (8.4), member classes (8.5), and instance initializers (8.6) of the anonymous class. The constructor of an anonymous class is always implicit (15.9.5.1).
If the class instance creation expression uses <>
with an anonymous class, then for all non-private
methods declared in the class body, it is as if the method declaration is annotated with @Override
(9.6.4.4).
When
<>
is used, the inferred type arguments may not be as anticipated by the programmer. Consequently, the supertype of the anonymous class may not be as anticipated, and methods declared in the anonymous class may not override supertype methods as intended. Treating such methods as if annotated with@Override
(if they are not explicitly annotated with@Override
) helps avoid silently incorrect programs.