This document describes changes to the Java Language Specification to support sealed types, a preview feature of Java SE 15. See JEP 360 for an overview of the feature.
A companion document describes the changes needed to the Java Virtual Machine Specification to support sealed types.
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.8 Identifiers
An identifier is an unlimited-length sequence of Java letters and Java digits, the first of which must be a Java letter.
- Identifier:
- IdentifierChars but not a Keyword or BooleanLiteral or NullLiteral
- IdentifierChars:
- JavaLetter {JavaLetterOrDigit}
- JavaLetter:
- any Unicode character that is a "Java letter"
- JavaLetterOrDigit:
- any Unicode character that is a "Java letter-or-digit"
A "Java letter" is a character for which the method Character.isJavaIdentifierStart(int)
returns true.
A "Java letter-or-digit" is a character for which the method Character.isJavaIdentifierPart(int)
returns true.
The "Java letters" include uppercase and lowercase ASCII Latin letters
A-Z
(\u0041-\u005a
), anda-z
(\u0061-\u007a
), and, for historical reasons, the ASCII dollar sign ($
, or\u0024
) and underscore (_
, or\u005f
). The dollar sign should be used only in mechanically generated source code or, rarely, to access pre-existing names on legacy systems. The underscore may be used in identifiers formed of two or more characters, but it cannot be used as a one-character identifier due to being a keyword.
The "Java digits" include the ASCII digits
0-9
(\u0030-\u0039
).
Letters and digits may be drawn from the entire Unicode character set, which supports most writing scripts in use in the world today, including the large sets for Chinese, Japanese, and Korean. This allows programmers to use identifiers in their programs that are written in their native languages.
An identifier cannot have the same spelling (Unicode character sequence) as a keyword (3.9), boolean literal (3.10.3), or the null literal (3.10.7), or a compile-time error occurs.
Two identifiers are the same only if, after ignoring characters that are ignorable, the identifiers have the same Unicode character for each letter or digit. An ignorable character is a character for which the method Character.isIdentifierIgnorable(int)
returns true. Identifiers that have the same external appearance may yet be different.
For example, the identifiers consisting of the single letters LATIN CAPITAL LETTER A (
A
,\u0041
), LATIN SMALL LETTER A (a
,\u0061
), GREEK CAPITAL LETTER ALPHA (A
,\u0391
), CYRILLIC SMALL LETTER A (a
,\u0430
) and MATHEMATICAL BOLD ITALIC SMALL A (a
,\ud835\udc82
) are all different.Unicode composite characters are different from their canonical equivalent decomposed characters. For example, a LATIN CAPITAL LETTER A ACUTE (
Á
,\u00c1
) is different from a LATIN CAPITAL LETTER A (A
,\u0041
) immediately followed by a NON-SPACING ACUTE (´
,\u0301
) in identifiers. See The Unicode Standard, Section 3.11 "Normalization Forms".
Examples of identifiers are:
String
i3
- αρετη
MAX_VALUE
isLetterOrDigit
The identifiers var
, and yield
, sealed
, and permits
are restricted identifiers because they are not allowed in some contexts.
A type identifier is an identifier that is not the character sequence var
, or the character sequence yield
.
A type identifier is an identifier that is not one of the following character sequences: permits
, sealed
, var
, or yield
.
- TypeIdentifier:
- Identifier but not
permits
,sealed
,var
, oryield
Type identifiers are used in certain contexts involving the declaration or use of types. For example, the name of a class must be a TypeIdentifier, so it is illegal to declare a class named
permits
,sealed
,var
, oryield
(8.1).
An unqualified method identifier is an identifier that is not the character sequence yield
.
- UnqualifiedMethodIdentifier:
- Identifier but not
yield
This restriction allows
yield
to be used in ayield
statement (14.21) and still also be used as a (qualified) method name for compatibility reasons.
3.9 Keywords
5152 character sequences, formed from ASCII letters, are reserved for use as keywords and cannot be used as identifiers (3.8).
- Keyword:
- (one of)
abstract double int strictfp
char for interface super
assert else long switch
boolean enum native synchronized
break extends new this
byte final
non-sealed
throw
case finally package throws
catch float private transient
class goto protected try
const if public void
continue implements return volatile
default import short while
do instanceof static _
(underscore)
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 variety of character sequences are sometimes assumed, incorrectly, to be keywords:
true
andfalse
are not keywords, but rather boolean literals (3.10.3).
null
is not a keyword, but rather the null literal (3.10.7).The restricted identifiers
var
,andyield
,sealed
andpermits
are not keywords.var
has special meaning as the type of a local variable declaration (14.4, 14.14.1, 14.14.2, 14.20.3) and the type of a lambda formal parameter (15.27.1).yield
has special meaning in ayield
statement (14.21). All invocations of a method calledyield
must be qualified so as to be distinguished from ayield
statement.sealed
andpermits
are used in class and interface declarations to limit subclassing and extension, respectively.
A further ten character sequences are restricted keywords: open
, module
, requires
, transitive
, exports
, opens
, to
, uses
, provides
, and with
. These character sequences are tokenized as keywords solely where they appear as terminals in the ModuleDeclaration, ModuleDirective, and RequiresModifier productions (7.7). They are tokenized as identifiers everywhere else, for compatibility with programs written before the introduction of restricted keywords. There is one exception: immediately to the right of the character sequence requires
in the ModuleDirective production, the character sequence transitive
is tokenized as a keyword unless it is followed by a separator, in which case it is tokenized as an identifier.
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 type identifier 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 type, 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 in a class type declaration (8.1)
An interface, declared in an interface type declaration (9.1)
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:
An enum constant (8.9)
A field, one of the following:
A method, one of the following:
A parameter, one of the following:
A formal parameter of a method or constructor of a class type or enum type (8.4.1, 8.8.1, 8.9.2), or of a lambda expression (15.27.1)
A formal parameter of an
abstract
method of an interface type or annotation type (9.4, 9.6.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:
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 14 15 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 qualified this
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 a try
-with-resources statement (15.14.1, 14.20.3)
13. 14. In a throws
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 eleven twelve non-generic contexts correspond to the first eleven twelve syntactic contexts for a TypeName in 6.5.1. The twelfth thirteenth non-generic context is where a qualified ExpressionName such as C.x
may include a TypeName C
to denote static member access. The common use of TypeName in these twelve thirteen contexts is significant: it indicates that these contexts involve a less-than-first-class use of a type. In contrast, the thirteenth fourteenth and fourteenth fifteenth non-generic contexts employ ClassType, indicating that throws
and catch
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).
The cross reference inserted above is a clarification to the existing JLS, unrelated to Sealed Types.
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.
Naming Conventions
The class libraries of the Java SE Platform attempt to use, whenever possible, names chosen according to the conventions presented below. These conventions help to make code more readable and avoid certain kinds of name conflicts.
We recommend these conventions for use in all programs written in the Java programming language. However, these conventions should not be followed slavishly if long-held conventional usage dictates otherwise. So, for example, the
sin
andcos
methods of the classjava.lang.Math
have mathematically conventional names, even though these method names flout the convention suggested here because they are short and are not verbs.
Package Names and Module Names
Developers should take steps to avoid the possibility of two published packages having the same name by choosing unique package names for packages that are widely distributed. This allows packages to be easily and automatically installed and catalogued. This section specifies a suggested convention for generating such unique package names. Implementations of the Java SE Platform are encouraged to provide automatic support for converting a set of packages from local and casual package names to the unique name format described here.
If unique package names are not used, then package name conflicts may arise far from the point of creation of either of the conflicting packages. This may create a situation that is difficult or impossible for the user or programmer to resolve. The classes
ClassLoader
andModuleLayer
can be used to isolate packages with the same name from each other in those cases where the packages will have constrained interactions, but not in a way that is transparent to a naïve program.
You form a unique package name by first having (or belonging to an organization that has) an Internet domain name, such as
oracle.com
. You then reverse this name, component by component, to obtain, in this example,com.oracle
, and use this as a prefix for your package names, using a convention developed within your organization to further administer package names. Such a convention might specify that certain package name components be division, department, project, machine, or login names.
Example 6.1-1. Unique Package Names
com.nighthacks.scrabble.dictionary
org.openjdk.compiler.source.tree
net.jcip.annotations
edu.cmu.cs.bovik.cheese
gov.whitehouse.socks.mousefinder
The first component of a unique package name is always written in all-lowercase ASCII letters and should be one of the top level domain names, such as
com
,edu
,gov
,mil
,net
, ororg
, or one of the English two-letter codes identifying countries as specified in ISO Standard 3166.
In some cases, the Internet domain name may not be a valid package name. Here are some suggested conventions for dealing with these situations:
If the domain name contains a hyphen, or any other special character not allowed in an identifier (3.8), convert it into an underscore.
If any of the resulting package name components are keywords (3.9), append an underscore to them.
If any of the resulting package name components start with a digit, or any other character that is not allowed as an initial character of an identifier, have an underscore prefixed to the component.
The name of a module should correspond to the name of its principal exported package. If a module does not have such a package, or if for legacy reasons it must have a name that does not correspond to one of its exported packages, then its name should still start with the reversed form of an Internet domain with which its author is associated.
Example 6.1-2. Unique Module Names
com.nighthacks.scrabble
org.openjdk.compiler
net.jcip.annotations
The first component of a package or module name must not be the identifier
java
. Package and module names that start with the identifierjava
are reserved for packages and modules of the Java SE Platform.
The name of a package or module is not meant to imply where the package or module is stored on the Internet. For example, a package named
edu.cmu.cs.bovik.cheese
is not necessarily obtainable from the hostcmu.edu
orcs.cmu.edu
orbovik.cs.cmu.edu
. The suggested convention for generating unique package and module names is merely a way to piggyback a package and module naming convention on top of an existing, widely known unique name registry instead of having to create a separate registry for package and module names.
Class and Interface Type Names
Names of class types should be descriptive nouns or noun phrases, not overly long, in mixed case with the first letter of each word capitalized.
Example 6.1-3. Descriptive Class Names
`ClassLoader`
SecurityManager
`Thread`
Dictionary
BufferedInputStream
Likewise, names of interface types should be short and descriptive, not overly long, in mixed case with the first letter of each word capitalized. The name may be a descriptive noun or noun phrase, which is appropriate when an interface is used as if it were an abstract superclass, such as interfaces
java.io.DataInput
andjava.io.DataOutput
; or it may be an adjective describing a behavior, as for the interfacesRunnable
andCloneable
.
Type Variable Names
Type variable names should be pithy (single character if possible) yet evocative, and should not include lower case letters. This makes it easy to distinguish type parameters from ordinary classes and interfaces.
Container types should use the name
E
for their element type. Maps should useK
for the type of their keys andV
for the type of their values. The nameX
should be used for arbitrary exception types. We useT
for type, whenever there is not anything more specific about the type to distinguish it. (This is often the case in generic methods.)
If there are multiple type parameters that denote arbitrary types, one should use letters that neighbor
T
in the alphabet, such asS
. Alternately, it is acceptable to use numeric subscripts (e.g.,T1
,T2
) to distinguish among the different type variables. In such cases, all the variables with the same prefix should be subscripted.
If a generic method appears inside a generic class, it is a good idea to avoid using the same names for the type parameters of the method and class, to avoid confusion. The same applies to nested generic classes.
Example 6.1-4. Conventional Type Variable Names
When type parameters do not fall conveniently into one of the categories mentioned, names should be chosen to be as meaningful as possible within the confines of a single letter. The names mentioned above (
E
,K
,V
,X
,T
) should not be used for type parameters that do not fall into the designated categories.
Method Names
Method names should be verbs or verb phrases, in mixed case, with the first letter lowercase and the first letter of any subsequent words capitalized. Here are some additional specific conventions for method names:
Methods to get and set an attribute that might be thought of as a variable V should be named
getV
andsetV
. An example is the methodsgetPriority
andsetPriority
of classThread
.A method that returns the length of something should be named
length
, as in classString
.A method that tests a boolean condition V about an object should be named
isV
. An example is the methodisInterrupted
of classThread
.A method that converts its object to a particular format F should be named
toF
. Examples are the methodtoString
of classObject
and the methodstoLocaleString
andtoGMTString
of classjava.util.Date
.
Whenever possible and appropriate, basing the names of methods in a new class on names in an existing class that is similar, especially a class from the Java SE Platform API, will make it easier to use.
Field Names
Names of fields that are not
final
should be in mixed case with a lowercase first letter and the first letters of subsequent words capitalized. Note that well-designed classes have very fewpublic
orprotected
fields, except for fields that are constants (static
final
fields).
Fields should have names that are nouns, noun phrases, or abbreviations for nouns.
Examples of this convention are the fields
buf
,pos
, andcount
of the classjava.io.ByteArrayInputStream
and the fieldbytesTransferred
of the classjava.io.InterruptedIOException
.
Constant Names
The names of constants in interface types should be, and
final
variables of class types may conventionally be, a sequence of one or more words, acronyms, or abbreviations, all uppercase, with components separated by underscore "_
" characters. Constant names should be descriptive and not unnecessarily abbreviated. Conventionally they may be any appropriate part of speech.
Examples of names for constants include
MIN_VALUE
,MAX_VALUE
,MIN_RADIX
, andMAX_RADIX
of the classCharacter
.
A group of constants that represent alternative values of a set, or, less frequently, masking bits in an integer value, are sometimes usefully specified with a common acronym as a name prefix.
For example:
Local Variable and Parameter Names
Local variable and parameter names should be short, yet meaningful. They are often short sequences of lowercase letters that are not words, such as:
Acronyms, that is the first letter of a series of words, as in
cp
for a variable holding a reference to aColoredPoint
Abbreviations, as in
buf
holding a pointer to a buffer of some kindMnemonic terms, organized in some way to aid memory and understanding, typically by using a set of local variables with conventional names patterned after the names of parameters to widely used classes. For example:
in
andout
, whenever some kind of input and output are involved, patterned after the fields ofSystem
off
andlen
, whenever an offset and length are involved, patterned after the parameters to theread
andwrite
methods of the interfacesDataInput
andDataOutput
ofjava.io
One-character local variable or parameter names should be avoided, except for temporary and looping variables, or where a variable holds an undistinguished value of a type. Conventional one-character names are:
b
for abyte
c
for achar
d
for adouble
e
for anException
f
for afloat
i
,j
, andk
forint
sl
for along
o
for anObject
s
for aString
v
for an arbitrary value of some type
Local variable or parameter names that consist of only two or three lowercase letters should not conflict with the initial country codes and domain names that are the first component of unique package names.
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:
The first
eleventwelve non-generic contexts (6.1):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 type (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 type 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 type.
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). 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 named reference type.
There are two kinds of class declarations: normal class declarations and enum declarations.
- ClassDeclaration:
- NormalClassDeclaration
- EnumDeclaration
- NormalClassDeclaration:
- {ClassModifier}
class
TypeIdentifier [TypeParameters]
[Superclass] [Superinterfaces]
[PermittedSubclasses] ClassBody
The rules in this section apply to all class declarations, including enum declarations. However, special rules apply to enum declarations with regard to class modifiers, inner classes, and superclasses; these rules are stated in 8.9.
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), not to local classes (14.3) or anonymous classes (15.9.5).
The access modifiers protected
and private
pertain only to member classes within a directly enclosing class declaration (8.5).
The modifier static
pertains only to member classes (8.5.1), not to top level or local or anonymous 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
, non-sealed
, and final
Classes
This subsection has a new title.
Extensibility of class hierarchies is an important feature of object-oriented programming. However, there are circumstances where explicit control of this extensibility is desirable.
A class can be declared sealed
when it is useful to restrict its direct subclasses to a fixed set of classes.
A class can be declared final
if its definition is complete and no subclasses are desired or required.
A class can be declared non-sealed
when it is useful to allow unrestricted direct subclasses.
A class is said to be extensible if it is not declared sealed
and is not declared final
. (A class that is declared non-sealed
is then extensible.)
If a class C has a sealed
direct superclass (8.1.4), or a sealed
direct superinterface (8.1.5), one of the following must apply otherwise a compile-time error occurs:
The class is an enum type (8.9).
The class is explicitly declared
final
orsealed
.The class is explicitly declared
non-sealed
, meaning that there are no restrictions on the subclasses of C.
JEP 359 proposes extending the Java language with Records, a special kind of class type, which is implicitly final
. In this case, we would add the following rule to the preceding list.
- The class is a record type.
It is a compile-time error if a class that does not have a sealed
direct superclass, or a sealed
direct superinterface, is declared non-sealed
.
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.
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).
8.1.4 Superclasses and Subclasses
The optional extends
clause in a normal class declaration specifies the direct superclass of the current class.
- Superclass:
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.
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
and the class being declared is not a permitted subclass of ClassType (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
or any invocation of Enum
(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.
Given a (possibly generic) class declaration C<
F1,...,Fn>
(n ≥ 0, C ≠ Object
), the direct superclass of the class type C<
F1,...,Fn>
is the type given in the extends
clause of the declaration of C if an extends
clause is present, or Object
otherwise.
Given a generic class declaration C<
F1,...,Fn>
(n > 0), the direct superclass of the parameterized class type C<
T1,...,Tn>
, where Ti (1 ≤ i ≤ n) is a type, is D<
U1 θ,...,Uk θ>
, where D<
U1,...,Uk>
is the direct superclass of C<
F1,...,Fn>
and θ is the substitution [
F1:=T1,...,Fn:=Tn]
.
A class is said to be a direct subclass of its direct superclass. The direct superclass is the class from whose implementation the implementation of the current class is derived.
The subclass relationship is the transitive closure of the direct subclass relationship. A class A is a subclass of class C if either of the following is true:
A is the direct subclass of C
There exists a class B such that A is a subclass of B, and B is a subclass of C, applying this definition recursively.
Class C is said to be a superclass of class A whenever A is a subclass of C.
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 type T if T 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 reference type T if any of the following is true:
C directly depends on T.
C directly depends on an interface I that depends (9.1.3) on T.
C directly depends on a class D that depends on T (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
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 the names of interfaces that are direct superinterfaces of the class being declared.
- Superinterfaces:
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
and the class being declared is not a permitted subtype of InterfaceType (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 mentioned as 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
This program results in a compile-time error because the names java.lang.Cloneable
and Cloneable
refer to the same interface.
Given a (possibly generic) class declaration C<
F1,...,Fn>
(n ≥ 0, C ≠ Object
), the direct superinterfaces of the class type C<
F1,...,Fn>
are the types given in the implements
clause of the declaration of C, if an implements
clause is present.
Given a generic class declaration C<
F1,...,Fn>
(n > 0), the direct superinterfaces of the parameterized class type C<
T1,...,Tn>
, where Ti (1 ≤ i ≤ n) is a type, are all types I<
U1 θ,...,Uk θ>
, where I<
U1,...,Uk>
is a direct superinterface of C<
F1,...,Fn>
and θ is the substitution [
F1:=T1,...,Fn:=Tn]
.
An interface type I is a superinterface of class type 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 implement all its superinterfaces.
A class may not at the same time be a subtype of two interface types which are different parameterizations of the same generic interface (9.1.2), or a subtype of a parameterization of a generic interface and a raw type naming that same generic interface, or 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
Class C
causes a compile-time error because it attempts to be a subtype of both I<Integer
> and I<String
>.
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).
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.
Example 8.1.5-3. Implementing Methods of a Superinterface
interface Colorable {
void setColor(int color);
int getColor();
}
class Point { int x, y; };
class ColoredPoint extends Point implements Colorable {
int color;
}
This program causes a compile-time error, because ColoredPoint
is not an abstract
class but fails to provide an implementation of methods setColor
and getColor
of the interface Colorable
.
In the following program:
interface Fish { int getNumberOfScales(); }
interface Piano { int getNumberOfScales(); }
class Tuna implements Fish, Piano {
// You can tune a piano, but can you tuna fish?
public int getNumberOfScales() { return 91; }
}
the method getNumberOfScales
in class Tuna
has a name, signature, and return type that matches the method declared in interface Fish
and also matches the method declared in interface Piano
; it is considered to implement both.
On the other hand, in a situation such as this:
interface Fish { int getNumberOfScales(); }
interface StringBass { double getNumberOfScales(); }
class Bass implements Fish, StringBass {
// This declaration cannot be correct,
// no matter what type is used.
public ?? getNumberOfScales() { return 91; }
}
it is impossible to declare a method named getNumberOfScales
whose signature and return type are compatible with those of both the methods declared in interface Fish
and in interface StringBass
, because a class cannot have multiple methods with the same signature and different primitive return types (8.4). Therefore, it is impossible for a single class to implement both interface Fish
and interface StringBass
(8.4.8).
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.
Unlike normal class declarations, the declaration of a class that is sealed
specifies which classes may be an extension of the sealed
class.
A sealed
class declaration C has a permits
clause, declared explicitly or implicitly, which provides a non-empty list of the names of the classes that are allowed to be an extension of C.
- PermittedSubclasses
permits
TypeName {,
TypeName }
Every TypeName must denote the name of a type that is accessible (6.6); otherwise a compile-time error occurs.
It is a compile-time error if any TypeName denotes a type variable.
It is a compile-time error if any TypeName denotes the name of class C, or the name of a class that is a superclass of C (8.1.4), or the name of any interface type (8.1.5).
It is a compile-time error if the name of a class appears more than once in a single permits
clause. This is true even if the class is named in different ways.
It is a compile-time error if any class named in a permits
clause of a sealed
class declaration C is not a member of the same module as C. If the sealed
class C is a member of the unnamed module, then it is a compile-time error if any class named in the permits
clause of the declaration of C is not in the same package as C.
A sealed
class declaration C without an explicitly declared permits
clause has an implicitly declared permits
clause containing the names of all the classes declared in the same compilation unit (7.3) whose direct superclass (4.10.2) has the same name as C.
It is a compile-time error for a sealed
class declaration to have an empty permits
clause.
This means that it is a compile-time error to declare a
sealed
class C, that has nopermits
clause, and there are no other classes declared in the same compilation unit whose direct superclass has the same name as C.
It is a compile-time error if a class declaration has an explicit permits
clause but is not sealed
.
It is a compile-time error if a class A is named in the permits
clause of a sealed
class declaration C, and C is not a direct superclass (8.1.4) of A.
A class A is a permitted direct subclass of a class C, if A is a direct subclass (8.1.4) of C, and A is named in the permits
clause of the declaration of C.
8.9 Enum Types
An enum declaration specifies a new enum type, a special kind of class type.
- EnumDeclaration:
- {ClassModifier}
enum
TypeIdentifier [Superinterfaces] EnumBody
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).
A nested enum type is implicitly static
. It is permitted for the declaration of a nested enum type to redundantly specify the static
modifier.
This implies that it is impossible to declare an enum type in the body 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).
The direct superclass of an enum type E is Enum<
E>
(8.1.4).
An enum type has no instances other than those defined by its enum constants. It is a compile-time error to attempt to explicitly instantiate an enum type (15.9.1).
In addition to the compile-time error, three further mechanisms ensure that no instances of an enum type 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 types is prohibited.
Special treatment by the serialization mechanism ensures that duplicate instances are never created as a result of deserialization.
Chapter 9: Interfaces
An interface declaration introduces a new reference type whose members are classes, interfaces, constants, and methods. This type has no 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.
A nested interface is any interface whose declaration occurs within the body of another class or interface.
A top level interface is an interface that is not a nested interface.
We distinguish between two kinds of interfaces - normal interfaces and annotation types.
This chapter discusses the common semantics of all interfaces - normal interfaces, both top level (7.6) and nested (8.5, 9.5), and annotation types (9.6). Details that are specific to particular kinds of interfaces are discussed in the sections dedicated to these constructs.
Programs can use interfaces to make it unnecessary for related classes to share a common abstract
superclass or to add methods to Object
.
An interface may be declared to be a direct extension of one or more other interfaces, meaning that it inherits all the member types, 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 a superclass.
Unlike a class, an interface cannot be declared final
. However, an interface may be declared sealed
(9.1.1.3), in which case it specifies a fixed set of classes and interfaces that may directly implement or extend the sealed interface. An interface may also be declared non-sealed
when it is useful to specify that there is no restriction on the classes and interfaces that may directly implement or extend the 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 a new named reference type. There are two kinds of interface declarations - normal interface declarations and annotation type declarations (9.6).
- InterfaceDeclaration:
- NormalInterfaceDeclaration
- AnnotationTypeDeclaration
- NormalInterfaceDeclaration:
- {InterfaceModifier}
interface
TypeIdentifier [TypeParameters]
[ExtendsInterfaces] [PermittedSubtypes] 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 access modifier public
(6.6) pertains to every kind of interface declaration.
The access modifiers protected
and private
pertain only to member interfaces whose declarations are directly enclosed by a class declaration (8.5.1).
The modifier static
pertains only to member interfaces (8.5.1, 9.5), not to top level interfaces (7.6).
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 declaration has more than one of the interface modifiers 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.3 sealed
and non-sealed
Interfaces
This is a new section.
An interface can be declared sealed
when it is useful to restrict its direct subtypes to a fixed set of classes and interfaces.
In certain circumstances, an interface can be declared non-sealed
to allow unrestricted direct subtypes.
If an interface I has a sealed
direct superinterface (9.1.3), one of the following must apply otherwise a compile-time error occurs:
The interface I is explicitly declared
sealed
.The interface I is explicitly declared
non-sealed
, meaning that there are no restrictions on the subtypes of I.
It is a compile-time error if an interface that does not have a sealed
superinterface is declared non-sealed
.
9.1.3 Superinterfaces and Subinterfaces
If an extends
clause is provided, then the interface being declared extends each of the other named interfaces and therefore inherits the member types, instance methods, and constants of each of the other named interfaces.
These other named interfaces are the direct superinterfaces of the interface being declared.
Any class that implements
the declared interface is also considered to implement all the interfaces that this interface extends
.
- ExtendsInterfaces:
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
, and the interface being declared is not a permitted subtype of InterfaceType (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.
Given a (possibly generic) interface declaration I<
F1,...,Fn>
(n ≥ 0), the direct superinterfaces of the interface type I<
F1,...,Fn>
are the types given in the extends
clause of the declaration of I, if an extends
clause is present.
Given a generic interface declaration I<
F1,...,Fn>
(n > 0), the direct superinterfaces of the parameterized interface type I<
T1,...,Tn>
, where Ti (1 ≤ i ≤ n) is a type, are all types J<
U1 θ,...,Uk θ>
, where J<
U1,...,Uk>
is a direct superinterface of I<
F1,...,Fn>
and θ is the substitution [
F1:=T1,...,Fn:=Tn]
.
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.
There exists an interface J such that K is a superinterface of J, and J is a superinterface of I, applying this definition recursively.
Interface I is said to be a subinterface of interface K whenever K is a superinterface of I.
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 type T if T 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 reference type T if any of the following is true:
I directly depends on T.
I directly depends on a class C that depends on T (8.1.5).
I directly depends on an interface J that depends on T (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 Subtypes
This is a new subsection. The existing subsection 9.1.4 "Interface Body and Member Declarations" is renumbered to 9.1.5.
Unlike normal interface declarations, the declaration of an interface that is sealed
specifies which classes may be a direct implementation of the sealed
interface, as well as which interfaces can be a direct extension of the sealed
interface.
A sealed
interface declaration I has a permits
clause, declared explicitly or implicitly, which provides a non-empty list of the names of the classes that are allowed to be an implementation of I, and the names of the interfaces that are allowed to be an extension of I.
- PermittedSubtypes
permits
TypeName {,
TypeName }
Every TypeName must denote the name of a class or interface type that is accessible (6.6); otherwise a compile-time error occurs.
It is a compile-time error if any TypeName denotes a type variable.
It is a compile-time error if any TypeName denotes the name of interface I, or the name of an interface that is a superinterface of I (9.1.3).
It is a compile-time error if the name of a class or interface appears more than once in a single permits
clause. This is true even if the class or interface type is named in different ways.
It is a compile-time error if any class or interface type named in a permits
clause of a sealed
interface declaration I is not a member of the same module as I. If the sealed
interface I is a member of the unnamed module, then it is a compile-time error if any class or interface named in the permits
clause of the declaration of I is not in the same package as I.
A sealed
interface declaration I without an explicitly declared permits
clause has an implicitly declared permits
clause containing the names of all the classes and interfaces declared in the same compilation unit (7.3) whose direct superinterface (9.1.3) has the same name as I.
It is a compile-time error for a sealed
interface declaration to have an empty permits
clause.
This means that it is a compile-time error to declare a
sealed
interface I, that has nopermits
clause, and there are no other classes or interfaces declared in the same compilation unit whose direct superinterface has the same name as I.
It is a compile-time error if an interface declaration has an explicit permits
clause but is not sealed
.
It is a compile-time error if a class or interface type C is named in the permits
clause of a sealed
interface declaration I, and I is not a direct superinterface (8.1.5, 9.1.3) of C.
A class or interface type C is a permitted direct subtype of an interface I, if I is a direct superinterface (8.1.5, 9.1.3) of C, and C is named in the permits
clause of the declaration of I.
9.8 Functional Interfaces
A functional interface is an interface that is not declared sealed
, 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, 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 final
Classes sealed
, non-sealed
and final
Classes
final
ClassesThis subsection has been renamed. Existing references to 13.4.2 should be renumbered to 13.4.2.3.
13.4.2.1 sealed
Classes
If a class that was not declared sealed
is changed to be declared sealed
, then a VerifyError
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 is declared sealed
to no longer be declared sealed
does not break compatibility with pre-existing binaries.
13.4.2.2 non-sealed
Classes
Changing a class that is not declared non-sealed
to be declared non-sealed
does not break compatibility with pre-existing binaries.
Changing a class that is declared non-sealed
to no longer be declared non-sealed
does not, in itself, break compatibility with pre-existing binaries.
Although removing a
non-sealed
modifier from a class declaration does not break compatibility with pre-existing binaries, it is highly likely to not compile successfully.Suppose that a new version of
C
is produced:Whilst this is compatible with the existing binary for
I
, recompilingC
but notI
results in an error asC
implements asealed
interface but is neithersealed
,non-sealed
norfinal
(8.1.1.2).
13.4.2.3 final
Classes
This subsection was originally 13.4.2.
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.
13.4.4 Superclasses and Superinterfaces Superclasses, Superinterfaces and Permitted Direct Subtypes
This subsection has been renamed.
A ClassCircularityError
is thrown at load time if a class would be a superclass of itself. Changes to the class hierarchy that could result in such a circularity when newly compiled binaries are loaded with pre-existing binaries are not recommended for widely distributed classes.
Changing the direct superclass or the set of direct superinterfaces of a class type will not break compatibility with pre-existing binaries, provided that the total set of superclasses or superinterfaces, respectively, of the class type loses no members.
If a change to the direct superclass or the set of direct superinterfaces results in any class or interface no longer being a superclass or superinterface, respectively, then linkage errors may result if pre-existing binaries are loaded with the binary of the modified class. Such changes are not recommended for widely distributed classes.
Example 13.4.4-1. Changing A Superclass
Suppose that the following test program:
class Hyper { char h = 'h'; }
class Super extends Hyper { char s = 's'; }
class Test extends Super {
public static void printH(Hyper h) {
System.out.println(h.h);
}
public static void main(String[] args) {
printH(new Super());
}
}
is compiled and executed, producing the output:
h
Suppose that a new version of class Super
is then compiled:
This version of class Super
is not a subclass of Hyper
. If we then run the existing binaries of Hyper
and Test
with the new version of Super
, then a VerifyError
is thrown at link time. The verifier objects because the result of new Super()
cannot be passed as an argument in place of a formal parameter of type Hyper
, because Super
is not a subclass of Hyper
.
It is instructive to consider what might happen without the verification step: the program might run and print:
s
This demonstrates that without the verifier, the Java type system could be defeated by linking inconsistent binary files, even though each was produced by a correct Java compiler.
The lesson is that an implementation that lacks a verifier or fails to use it will not maintain type safety and is, therefore, not a valid implementation.
The requirement that alternatives in a multi-
catch
clause (14.20) not be subclasses or superclasses of each other is only a source restriction. Assuming the following client code is legal:where
ExceptionA
andExceptionB
do not have a subclass/superclass relationship when the client is compiled, it is binary compatible with respect to the client forExceptionA
andExceptionB
to have such a relationship when the client is executed.This is analogous to other situations where a class transformation that is binary compatible for a client might not be source compatible for the same client.
Changing the set of permitted direct subclasses of a class (8.1.6) or permitted direct subtypes of an interface (9.1.4) may result in linkage errors if pre-existing binaries are loaded with the binary of the modified class or interface. Such changes are not recommended for widely distributed classes or interfaces.
Chapter 14: Blocks and Statements
14.3 Local Class Declarations
A local class is a nested class (8) that is not a member of any class and that has a name (6.2, 6.7).
All local classes are inner classes (8.1.3).
Every local class declaration statement is immediately contained by a block (14.2). Local class declaration statements may be intermixed freely with other kinds of statements in the block.
It is a compile-time error if a local class declaration contains any of the access modifiers public
, protected
, or private
(6.6), or any of the modifier modifiers static
(8.1.1), sealed
or non-sealed
(8.1.1.2).
The scope and shadowing of a local class declaration is specified in 6.3 and 6.4.
Example 14.3-1. Local Class 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.5 Anonymous Class Declarations
An anonymous class declaration is automatically derived from a class instance creation expression by the Java compiler.
An anonymous class is never abstract
(8.1.1.1).
An anonymous class is never final
(8.1.1.2).
An anonymous class is never sealed
(8.1.1.2).
The fact that an anonymous class is not
final
is relevant in casting, in particular the narrowing reference conversion allowed for the cast operator (5.5). It is also of interest in subclassing, in that it is impossible to declare a subclass of an anonymous class, despite an 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); it is never static
(8.1.1, 8.5.1).
The superclass or superinterface of an anonymous class is given by the class instance creation expression (15.9.1), with type arguments inferred as necessary while choosing a constructor (15.9.3).
It is a compile-time error if the superclass or superinterface of an anonymous class is sealed
(8.1.1.2, 9.1.1.3).
If the class instance creation expression uses <>
with an anonymous class, then for all non-private
methods declared in the anonymous 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.