Project Coin/JSR 334 is an effort to add a set of small language changes to Java SE 7 under the JSR 336 umbrella JSR with the reference implementation developed in OpenJDK. The changes must be simultaneously small in specification, implementation, and testing. The small changes to the Java programming language in Java SE 7 are:
Binary integral literals and underscores in numeric literals
Improved Type Inference for Generic Instance Creation (diamond)
A description of the semantics for each feature as implemented in JDK 7 build b143 will follow. Non-normative discussion will appear in block quotes as below:
Discussion: Text appearing here is only informative.
The documentation for a language change includes updates to the Java™ Language
Specification, Third Edition (JLSv3) and may also include
supporting library changes.
Since the changes will in part be phrased as differences from existing
JLSv3 text, having the JLSv3 text available to provide context is
recommended for a close reading of this document.
The full text of JLSv3 is available online.
Text that is deleted from JLSv3
will be displayed like this,
while text that is added
will be rendered this way.
The language changes as given in this document may at times be less
formal than the eventual JLSv3 updates.
Readers should review the discussion section of a feature before
sending in a comment or question about that feature.
Previous discussions of design considerations may appear in the
coin-dev
archives.
For informational purposes, a summary of changes to the JSR 269 API in
the javax.lang.model.*
packages is given in an appendix.
Some of the changes have been made to directly support new
language features; other changes are usability improvements to the
API.
These changes have gone through a maintenance
review of JSR 269 for inclusion in the JSR 336 umbrella JSR for
Java SE 7.
The list of types which can be switched on in JLSv3
§14.11 "The switch Statement" is augmented to include
String
:
"The type of the Expression must bechar
,byte
,short
,int
,Character
,Byte
,Short
,Integer
,String
, or an enum type (§8.9), or a compile-time error occurs."
No other explicit changes are necessary to support switching on a string.
Discussion: The lexical grammar of the switch statement does not need to be changed to support switching on a string since the
String
is already included in the definition of constant expressions, JLSv3 §15.28, so the SwitchLabel production does not need to be augmented. The existing restrictions in JLSv3 §14.11 on no duplicate labels, at most one default, nonull
labels, etc. all apply toString
labels without modification. The definite assignment analysis of the switch statement, JLSv3 §16.2.9, is unchanged as well.The existing rules for the
switch
statement forbid anull
label and require aNullPointerException
to be thrown if the expression being switched on isnull
. Anull
expression can occur for both enum types and for boxed primitive types likeInteger
andFloat
. Therefore, consistency alone argues for these prohibitions to also be in place when switching on a string.The prohibition on duplicate string labels applies after any encoding step which maps a sequence of bytes of the input file to a sequence of logical characters and after the specified Unicode escape lexical translations (JLSv3 §3.2) are applied. Therefore, labels that are textually distinct in the source code may still be regarded as being duplicates after these translations occur. Whether or not string labels are distinct may depend on the encoding used by the compiler to interpret the bytes of the input sources.
In order to keep strings in switch a small language change, the JVM lookupswitch and tableswitch instructions in Java SE 7 do not support switching on a string. Instead, Java compilers are responsible for translating a switch on strings into some sequence of byte code instructions with the proper semantics. Many valid and efficient translation schemes are possible that have better expected performance than successive comparisons of the string being switched on with each
case
label constant. Direct JVM support for switching on a string may be added in a future version of the platform.
Binary integer literals are structured just like hexadecimal integer
literals except that binary digits are used instead of hexadecimal
digits and binary literals are prefixed by "0b
" rather
than "0x
".
In numeric literals, underscores are allowed as separators between digits. This applies to literals in any supported base: binary, octal, hexadecimal, or decimal and applies both to integer literals (§3.10.1) and floating-point literals (§3.10.2).
The grammar changes below are additions or modifications to JLSv3 §3.10.
- IntegerLiteral:
- DecimalIntegerLiteral
- HexIntegerLiteral
- OctalIntegerLiteral
- BinaryIntegerLiteral
- BinaryIntegerLiteral:
- BinaryNumeral IntegerTypeSuffixopt
- BinaryNumeral:
0
b
BinaryDigits0
B
BinaryDigits
- DecimalNumeral:
0
- NonZeroDigit Digitsopt
- NonZeroDigit Underscores Digits
- Underscores:
_
- Underscores
_
- Digits:
- Digit
Digits Digit- Digit DigitsAndUnderscoresopt Digit
- DigitsAndUnderscores:
- DigitOrUnderscore
- DigitsAndUnderscores DigitOrUnderscore
- DigitOrUnderscore:
- Digit
_
- HexDigits:
- HexDigit
- HexDigit
HexDigitsHexDigitsAndUnderscoresopt HexDigit
- HexDigitsAndUnderscores:
- HexDigitOrUnderscore
- HexDigitsAndUnderscores HexDigitOrUnderscore
- HexDigitOrUnderscore:
- HexDigit
_
- OctalNumeral:
0
OctalDigits0
Underscores OctalDigits
- OctalDigits:
- OctalDigit
- OctalDigit
OctalDigitsOctalDigitsAndUnderscoresopt OctalDigit
- OctalDigitsAndUnderscores:
- OctalDigitOrUnderscore
- OctalDigitsAndUnderscores OctalDigitOrUnderscore
- OctalDigitOrUnderscore:
- OctalDigit
_
- BinaryDigits:
- BinaryDigit
- BinaryDigit BinaryDigitsAndUnderscoresopt BinaryDigit
- BinaryDigitsAndUnderscores:
- BinaryDigitOrUnderscore
- BinaryDigitsAndUnderscores BinaryDigitOrUnderscore
- BinaryDigitOrUnderscore:
- BinaryDigit
_
- BinaryDigit: one of
0
1
No other language changes are necessary to support the new literal syntax.
Discussion: As written, due to reuse of the productions, these grammar changes imply underscores as separators are supported both in integral literals (for
int
,long
,short
, etc.) as well as for floating-point literals without explicit changes to the section describing floating-point literals. Therefore allowed uses of underscores include:
1234_5678
1_2_3_4__5_6_7_8L
0b0001_0010_0100_1000
3.141_592_653_589_793d
0x1.ffff_ffff_ffff_fP1_023 // Double.MAX_VALUE
while disallowed uses of underscores include:
_1234
0x_1234
1234_
0x1.0_p_-1022
The grammar above for the literals is unambiguous, but as written requires a lookahead of more than 1 character because the recursion is in the middle of the Digits production. Since the underscores are separators, productions like
- Digits:
- Digit DigitsAndUnderscoresopt
would not be correct since an underscore could appear as a terminator of the literal. Since the lexical grammar has expository purposes, no attempt has been made to refactor the grammar to restore a look ahead of 1. In addition, in practice the underscores may be purged with a small amount of additional logic in a compiler's scanner as opposed to its parser proper.
Since the leading "
0
" used to specify an octal literal is itself a digit, underscores are allowed between the leading0
and subsequent value-carrying digits of an octal literal. This differs from the treatment of the hexadecimal and binary literal specifiers, "0x
" and "0b
", which are not made up entirely of digit characters of the base in question.The expert group has discussed limiting underscores between digits to a single underscore rather than the multiple underscores currently allowed. The kernel of the single-underscore grammar would be:
- Digits:
- DigitsAndUnderscoresopt Digit
- DigitsAndUnderscores:
- Digit Underscoreopt DigitsAndUnderscoresopt
- Underscore:
_
Allowing at most one underscore could prevent some abuses of the feature, at the cost of outlawing some potentially helpful syntactic alignment and introducing a restriction on underscores not present in the use of underscores in identifier names.
Currently the methods in the
java.lang
package that convert strings to primitive numeric values do not support converting inputs strings with underscores (Oracle bug 6863378). This capability might be added in the future.
Two changes are made to exception handling.
First, multiple exception types can be named as being handled by a
single catch
block.
Second, if an exception parameter is not modified and if it is
rethrown inside the catch
block, the compiler applies a
more precise analysis to determine the type of what can be thrown.
To support catching multiple exception types, various specification
changes in JLSv3 are needed; first, the grammar of a
catch
clause of a try
statement (JLSv3 §14.20) is
extended to allow a series of exception types, separated by the "OR"
operator symbol, "|
", to be used in the declaration of
the exception parameter:
- CatchClause:
catch
(
FormalParameterCatchFormalParameter)
Block
- CatchFormalParameter:
- VariableModifiersopt CatchType VariableDeclaratorId
...
- CatchType:
- ClassType
- ClassType
|
CatchTypeA
try
statement may havecatch
clauses (also called exception handlers). Acatch
clause must have exactly one parameter (which is called an exception parameter); the declared type of the exception parameter can be a single class type or can be a union type (denoted with '|
') between two or more class types (or alternatives). Acatch
clause with a union type parameter is called a multi-catch
clause. For the purposes of type-checking, a union type D with alternatives D1, D2 ... Dn has type lub(D1, D2 ... Dn) (§15.12.2.7). It is a compile-time error if a union type contains two alternatives Di, Dj where Di is a subtype of Dj.Each class type used in the declaration of an exception parameter must be the class
...Throwable
or a subclass (not just a subtype) ofThrowable
, or a compile-time error occurs. In particular, it is a compile-time error if the declared type of the exception parameter is a type variable (§4.4).
The notion of finality in JLSv3 §4.12.4 final Variables is expanded to include effectively final:
An exception parameter whose type is a union type is implicitly considered to be final.
In addition, an exception parameter that is not declared
final
may instead be considered effectively final if it never occurs as the left hand operand of an assignment operator.If an exception parameter is effectively final, adding the
final
modifier to its declaration will not introduce any compile time errors. Conversely, an exception parameter that is declaredfinal
in a valid program becomes effectively final if thefinal
modifier is removed.
Changing the handling of exception types affects the type system in
two ways: in addition to the usual type checking performed on all
types, exception types undergo an additional compile time analysis.
For the purpose of type checking, an exception parameter declared with
a union has type lub(D1, D2,
...) (JLSv3 §15.12.2.7) where the Di
are the exception types the catch
clause is declared to
handle.
Informally, the lub (least upper bound) is the most specific supertype
of the types in question.
In the case of a multi-catch exception parameter, the least upper
bound of the types in question always exists since the types of all
the caught exceptions must be subclasses of Throwable
.
Therefore, Throwable
is an upper bound of the
types in question, but it may not be the least upper bound
since some subclass of Throwable
may be a superclass (and
thereby also a supertype) of the types in question and the exception
types in question may implement a common interface.
(A lub can be an intersection type of a superclass and one or more
interfaces.)
For the purpose of exception checking (JLSv3
§11.2), the rules for a throw
statement (JLSv3
§11.2.2) are modified:
A
throw
statement whose thrown expression has static type E can throw E or any subtype of E, or any exception type thrown by the thrown expression. However, when the thrown expression is afinal
or effectively final (§4.12.4) exception parameter ej of acatch
clause Cj, thethrow
statement instead can throw any exception type T that meets the following conditions:
- The
try
block of thetry
statement which declares Cj can throw T.- For all exception parameters ei declared by any
catch
clauses Ci, 1 ≤ i < j , declared to the left of Cj for the sametry
statement, T is not assignable to ei.- T is assignable to ej.
Informally, if the catch
parameter is not modified and if
the exception is rethrown, the compiler knows the exception is one of
the exceptions throwable by the try
block and not already
handled by some earlier catch
block.
This determination of the types that can be thrown can be more
precise, meaning more specific than, the declared type of the
catch
parameter.
Rules are added to JLSv3 §11.2.3 Exception Checking to support exception checking when exception parameters have union types:
...An instance variable initializer in an anonymous class (§15.9.5) can throw any exception.
For the purposes of exception checking, a
try
statement declaring one or morecatch
clauses whose declared type is a union type can be normalized into atry
statement declaring a sequence of plaincatch
clauses without union types. More specifically, the normalization process turns acatch
clause whose exception parameter has a declared type of the form D1|D2 ... Dn into a sequence of n plaincatch
clauses whose exception parameters have types D1, D2, ..., Dn, respectively.
Discussion: Consider the following code:try { //throws some ReflectiveOperationException }
catch (ClassNotFoundError | IllegalAccessException ex) { //body }The the purposes of exception checking, above code is semantically equivalent to the following code:try { //throws some ReflectiveOperationException }
catch (final ClassNotFoundException ex1) { //body }
catch (final IllegalAccessException ex2) { //body }in which thecatch
clause with a union type having two alternatives has been normalized into two separatelycatch
clauses, one for each alternative. This normalization process does not introduce any new compile-time errors.However, note that Java compilers are neither required nor recommended to compile a
catch
clause with an exception parameter with a union type by duplicating code since it is possible represent this computation in a class file without such duplication.
It is a compile-time error if a
catch
clause of a normalizedtry
statement catches ...
Discussion: Since it is implicitly final, an explicit
final
on a multi-catch exception parameter is legal, but discouraged as a matter of style.There are contrived cases where the more precise exception analysis can stop compilation of currently valid programs (by the compiler identifying more dead code); one example is:
try { throw new DaughterOfFoo(); } catch (Foo e) { try { throw e; // used to throw Foo, now throws DaughterOfFoo } catch (SonOfFoo anotherException) { // Reachable? } }This will compile under source 6 and earlier using the imprecise analysis (the rethrow of
e
is regarded as beingFoo
or some subclass ofFoo
), but will not compile under the more precise analysis since the compiler will correctly view "catch (SonOfFoo ...)
" as unreachable. An examination of millions of lines of code in a diverse set of projects, including dozens of members of the Qualitas Corpus and the JDK, found no instances where these conditions occurred. Therefore, using a more precise exception analysis when recompiling existing code is viewed as having acceptable source compatibility risk. If the source can be modified, removing the dead code from the code would resolve the problem.Fuller support for union types may be added in future releases; forcing union
catch
parameters to be implicitly or explicitlyfinal
preserves flexibility in evolving the language if fuller support is added in the future.The exception alternatives in a
catch
clause with a union type must be disjoint, one cannot be a subclass of another. In particular, since a type is a subtype of itself, it is illegal to have duplicated class types in the declaration of an exception parameter. It would be possible to define reasonable semantics when a true superclass/subclass relationship existed between two alternatives, namely to logically remove the subclass from the list of alternatives. While allowing superclass/subclass exceptions would provide source compatibility robustness to changes in exception hierarchies, prohibition of superclass/subclass relationships offers a number of design advantages. First, if deemed helpful, such relationships can be allowed in future releases in a compatible fashion. Since the exceptions types are disjoint, the results of the normalization process to single-typecatch
clauses are independent of the ordering of the alternatives. (If superclass/subclass relationships were supported, either the subclasses would have to be removed before normalization or a topological sort of the exception types would need to be performed, putting superclasses after subclasses.)As an implication of the
catch
clause normalization, each type alternative must be able to catch some exception for the program to be legal. For example, the following statement would causes a compile time error since the use ofSonOfFoo
is not active:try {...} catch(Foo f) {...} catch(Bar | SonOfFoo e) {....}Starting with legal code in a class
Client
liketry { throwAorB(); } catch(ExceptionA | ExceptionB e) { ... }where
ExceptionA
andExceptionB
are in a separate library and do not have superclass/subclass relationship whenClient
is compiled, it is binary compatible with respect toClient
forExceptionA
andExceptionB
to have such a relationship whenClient
is run. This is analogous to other situations where a transformation to library classes that is binary compatible for a client might not be source compatible for the same client.The revised exception analysis for
final
and effectivelyfinal
catch
parameters is more precise than the previously defined analysis. Therefore, when the new analysis is applied to existing code, allthrows
clauses on methods and constructors remain valid.
The diamond language change allows explicit type arguments to constructors of parameterized classes, most notably collections, to be omitted in many situations since the compiler is able to infer the arguments on behalf of the programmer.
First, the grammatical changes to support diamond occur in JLSv3 §15.9 and affect the ClassInstanceCreationExpression production:
- ClassInstanceCreationExpression:
new
TypeArgumentsoptClassOrInterfaceTypeTypeDeclSpecifier TypeArgumentsOrDiamondopt(
ArgumentListopt)
ClassBodyopt- Primary
.
new
TypeArgumentsopt IdentifierTypeArgumentsoptTypeArgumentsOrDiamondopt(
ArgumentListopt)
ClassBodyopt
- TypeArgumentsOrDiamond:
- TypeArguments
<
>
Next, the first paragraph of that section is changed:
A class instance creation expression specifies a class to be instantiated, possibly followed by type arguments or diamondLater in that section:"<>"
(if the class being instantiated is generic (§8.1.2)), followed by (a possibly empty) list of actual value arguments to the constructor. If the class type argument list is empty — the form "<>
" — the class type arguments are to be inferred.It is also possible to pass explicit type arguments to the constructor itself (if it is a generic constructor (§8.8.4)).If the constructor is generic (§8.8.4), the type arguments to the constructor may similarly either be inferred or explicitly passed. In the latter case,thesethe type arguments immediately follow the keyword new. Inference of class type arguments may influence the constraints on constructor type arguments. Thus, it is a compile-time error if a class instance creation expression provides a constructor type argument list but uses "<>
" in place of a class type argument list. It is also a compile-time error if any of the type arguments used in a class instance creation expression are wildcard type arguments (§4.5.1).
Both unqualified and qualified class instance creation expressions may
optionally end with a class body. Such a class instance creation
expression declares an anonymous class (§15.9.5)
and creates an instance of it.
It is a compile-time error if a class instance creation
expression declares an anonymous class but uses "<>"
in
place of a type argument list.
In JLSv3 §15.9.1,
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 an unqualified class instance creation expression,
then let T be the ClassOrInterfaceType after theTypeDeclSpecifier TypeArgumentsOrDiamondopt must denote a type, T (§4.3, §4.5), or a compile-time error occurs. It is also a compile-time error if the class or interface named by T is not accessible (§6.6) or if T is an enum type (§8.9). ...new
tokenOtherwise, the class instance creation expression is a qualified class instance creation expression.
Let T be the name of the Identifier after theIt is a compile-time error ifnew
token.Tthe Identifier after the new token is not the simple name (§6.2) of an accessible (§6.6) non-final
inner class (§8.1.3) that is a member of the compile-time type of the Primary. It is also a compile-time error ifTthe name is ambiguous (§8.5) or ifTit denotes an enum type. When TypeArguments have been provided after the name, it is a compile-time error if the type arguments, when applied to the named class or interface, do not denote a well-formed parameterized type (§4.5). Let T be the type named by the identifier and any type arguments. An anonymous direct subclass of the class named by T is declared. 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 an unqualified class instance creation expression, then the
ClassOrInterfaceTypeTypeDeclSpecifier must denote a class that is accessible (§6.6) and is not an enum type and notabstract
, or a compile-time error occurs. When TypeArguments have been provided after the class name, it is a compile-time error if the type arguments, when applied to the class, do not denote a well-formed parameterized type (§4.5). When"<>"
is instead used to elide type arguments after the class name, it is a compile-time error if the class is not generic.In this case, theThe class being instantiated is the class denoted byClassOrInterfaceTypethe TypeDeclSpecifier.Otherwise, the class instance creation expression is a qualified class instance creation expression. It is a compile-time error if Identifier is not the simple name (§6.2) of an accessible (§6.6) non-
abstract
inner class (§8.1.3)TC that is a member of the compile-time type of the Primary. It is also a compile-time error if Identifier is ambiguous (§8.5), or if Identifier denotes an enum type (§8.9). When TypeArguments have been provided after the name, it is a compile-time error if the type arguments, when applied to C, do not denote a well-formed parameterized type (§4.5). When"<>"
is instead used to elide type arguments after the name, it is a compile-time error if C is not generic. The class being instantiated isthe class denoted by IdentifierC.The type of the class instance creation expression is the class type being instantiated.
In JLSv3 §15.9.3 (Choosing the Constructor and its Arguments),
Let C be the class
typebeing instantiated. To create an instance of C, i, a constructor of Cisand type of i are chosen at compile-time by the following rules. First, the actual arguments to the constructor invocation are determined.Second, a constructor of C and corresponding result type and throws clause are determined.
- If C is an anonymous class, and the direct superclass of C, S, is an inner class, then:
If the S is a local class and S occurs in a static context, then the arguments in the argument list, if any, are the arguments to the constructor, in the order they appear in the expression.
Otherwise, the immediately enclosing instance of i with respect to S is the first argument to the constructor, followed by the arguments in the argument list of the class instance creation expression, if any, in the order they appear in the expression.
- Otherwise the arguments in the argument list, if any, are the arguments to the constructor, in the order they appear in the expression.
The type of the class instance creation expression is the result type of the chosen constructor, as defined above. Note that
If the class instance creation expression uses
"<>"
to elide class type arguments, a list of methods m1...mk is defined for the purpose of overload resolution and type argument inference. Let c1...ck be the constructors of class C. Let x be a name that is not the name of any member method of C. For all j, 1≤j≤k, mj is defined in terms of cj as follows:
A substitution Θj is first defined to instantiate the types in cj. Let F1...Fp be the type parameters of C, and let G1...Gq be the type parameters of cj (if any). Let X1...Xp and Y1...Yq be type variables with distinct names that are not in scope in the body of C. Then Θj is [F1:=X1, ... , Fp:=Xp, G1:=Y1, ... ,Gq:=Yq].
The modifiers of mj are those of cj.
The type parameters of mj are X1,...,Xp, Y1,...,Yq. The bound of each parameter, if any, is Θj applied to the corresponding parameter bound in C or cj.
The return type of mj is Θj applied to C<F1...Fp>.
The name of mj is x.
The (possibly empty) list of argument types of mj is Θj applied to the argument types of cj.
The (possibly empty) list of thrown types of mj is Θj applied to the thrown types of cj.
The body of mj is irrelevant.
To choose a constructor, we temporarily consider m1...mk to be members of C. Then one of m1...mk is selected, as determined by the class instance creation's argument expressions, using the process described in §15.12.2. A compile-time error results if there is no unique most-specific method that is both applicable and accessible. Otherwise, where mj is the selected method, cj is the chosen constructor. The result type and throws clause of cj are the same as the return type and throws clause determined for mj (§15.12.2.6).
Otherwise, the class instance creation expression does not use
"<>"
to elide class type arguments. Let T be the type denoted by C followed by any class type arguments in the expression. The process described in §15.12.2, modified to handle constructors, is used to select one of the constructors of T and determine its throws clause.As in method invocations, a compile-time error results if there is no unique most-specific constructor that is both applicable and accessible. Otherwise, the result type is T.
the type of the class instance creation expressionthis type may be an anonymous class type, in which case the constructor being invoked is an anonymous constructor.
Discussion: Syntacticly, ClassOrInterfaceType expands to either a ClassType or InterfaceType (JLSv3 §4.3). Both ClassType and InterfaceType then in turn expand to
TypeDeclSpecifier TypeArgumentsopt
Therefore, "inlining" TypeDeclSpecifier for ClassOrInterfaceType followed by an optional TypeArgumentsOrDiamond captures the desired syntax.It is legal, but discouraged, to have white space between the "<" and ">" of a diamond.
Raw types have an existing meaning in Java programs and it is useful to maintain a distinction between raw types (hopefully in legacy code) and types inferred by the compiler. Therefore, the diamond syntax is used to mark locations where type inference is requested as opposed to interpreting all instances of raw types as inference sites.
Constructors with explicit type arguments can be assigned to variables having a raw type or a type with a wildcard:
List rawList = new ArrayList<Object>(); // Raw types discouraged, but legal List<?> wildList = new ArrayList<Object>();Consquently, diamond can be used on the left hand side of an assignment where the right hand size uses a raw type or a type with a wildcard:
List rawList = new ArrayList<>(); // Raw types strongly discouraged with diamond, but legal List<?> wildList = new ArrayList<>();In both cases, the compiler infers
Object
as the value of type argument for the constructor. This result is implied by the rules contained in JLSv3 §15.12.2. Allowing diamond in such locations eases retrofitting existing code to use diamond.Internally, a Java compiler operates over a richer set of types than those that can be written down explicitly in a Java program. The compiler-internal types which cannot be written in a Java program are called non-denotable types. Non-denotable types can occur as the result of the inference used by diamond. Therefore, using diamond with anonymous inner classes is not supported since doing so in general would require extensions to the class file signature attribute to represent non-denotable types, a de facto JVM change. It is feasible that future platform versions could allow use of diamond when creating an anonymous inner class as long as the inferred type was denotable.
try
-with-resources statement
The try
-with-resources feature includes a suite of
language and library changes to ease management of objects that
require an explicit call to a close
to free up some
underlying resource when the object is no longer in use.
Typical objects whose correct management can be assisted by
try
-with-resources include input streams and output
streams where native operating system resources need to be explicitly
freed since they are not managed by garbage collection.
The supporting library changes for try
-with-resources
feature are:
A new interface java.lang.AutoCloseable
.
Libraries retrofitted to implement the new interface.
Facilities to manage suppressed exceptions on
java.lang.Throwable
.
The new interface java.lang.AutoCloseable
:
package java.lang; /** * A resource that must be closed when it is no longer needed. * * @since 1.7 */ public interface AutoCloseable { /** * Closes this resource, relinquishing any underlying resources. * This method is invoked automatically on objects managed by the * {@code try}-with-resources statement. * * <p>While this interface method is declared to throw {@code * Exception}, implementers are strongly encouraged to * declare concrete implementations of the {@code close} method to * throw more specific exceptions, or to throw no exception at all * if the close operation cannot fail. * * <p>Implementers of this interface are also strongly advised * to not have the {@code close} method throw {@link * InterruptedException}. * * This exception interacts with a thread's interrupted status, * and runtime misbehavior is likely to occur if an {@code * InterruptedException} is {@linkplain Throwable#addSuppressed * suppressed}. * * More generally, if it would cause problems for an * exception to be suppressed, the {@code AutoCloseable.close} * method should not throw it. * * <p>Note that unlike the {@link java.io.Closeable#close close} * method of {@link java.io.Closeable}, this {@code close} method * is not required to be idempotent. In other words, * calling this {@code close} method more than once may have some * visible side effect, unlike {@code Closeable.close} which is * required to have no effect if called more than once. * * However, implementers of this interface are strongly encouraged * to make their {@code close} methods idempotent. * * @throws Exception if this resource cannot be closed */ void close() throws Exception; }
Types directly implementing or extending java.lang.AutoCloseable
:
java.beans.XMLDecoder
java.beans.XMLEncoder
java.io.Closeable
java.io.ObjectInput
java.io.ObjectOutput
java.sql.Connection
java.sql.ResultSet
java.sql.Statement
java.nio.channels.FileLock
(with an added close
method)
javax.sound.midi.MidiDevice
javax.sound.midi.Receiver
javax.sound.midi.Transmitter
javax.sound.sampled.Line
Types newly implementing or extending java.io.Closeable
:
java.util.Scanner
javax.imageio.stream.ImageInputStream
One constructor and two new methods are added to
java.lang.Throwable
to manage suppressed exceptions; in
addition, the serial format is updated:
/** * Constructs a new throwable with the specified detail message, * cause, {@linkplain #addSuppressed suppression} enabled or * disabled, and writable stack trace enabled or disabled. If * suppression is disabled, {@link #getSuppressed} for this object * will return a zero-length array and calls to {@link * #addSuppressed} that would otherwise append an exception to the * suppressed list will have no effect. If the writable stack * trace is false, this constructor will not call {@link * #fillInStackTrace()}, a {@code null} will be written to the * {@code stackTrace} field, and subsequent calls to {@code * fillInStackTrace} and {@link * #setStackTrace(StackTraceElement[])} will not set the stack * trace. If the writable stack trace is false, {@link * #getStackTrace} will return a zero length array. * * <p>Note that the other constructors of {@code Throwable} treat * suppression as being enabled and the stack trace as being * writable. Subclasses of {@code Throwable} should document any * conditions under which suppression is disabled and document * conditions under which the stack trace is not writable. * Disabling of suppression should only occur in exceptional * circumstances where special requirements exist, such as a * virtual machine reusing exception objects under low-memory * situations. Circumstances where a given exception object is * repeatedly caught and rethrown, such as to implement control * flow between two sub-systems, is another situation where * immutable throwable objects would be appropriate. * * @param message the detail message. * @param cause the cause. (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @param enableSuppression whether or not suppression is enabled or disabled * @param writableStackTrace whether or not the stack trace should be * writable * * @see OutOfMemoryError * @see NullPointerException * @see ArithmeticException * @since 1.7 */ protected Throwable(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) /** * The list of suppressed exceptions, as returned by {@link * #getSuppressed()}. The list is initialized to a zero-element * unmodifiable sentinel list. When a serialized Throwable is * read in, if the {@code suppressedExceptions} field points to a * zero-element list, the field is reset to the sentinel value. * * @serial * @since 1.7 */ private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL; /** * Appends the specified exception to the exceptions that were * suppressed in order to deliver this exception. This method is * thread-safe and typically called (automatically and implicitly) * by the {@code try}-with-resources statement. * * <p>The suppression behavior is enabled unless disabled * {@linkplain #Throwable(String, Throwable, boolean) via a * constructor}. When suppression is disabled, this method does * nothing other than to validate its argument. * * <p>Note that when one exception {@linkplain * #initCause(Throwable) causes} another exception, the first * exception is usually caught and then the second exception is * thrown in response. In other words, there is a causal * connection between the two exceptions. * * In contrast, there are situations where two independent * exceptions can be thrown in sibling code blocks, in particular * in the {@code try} block of a {@code try}-with-resources * statement and the compiler-generated {@code finally} block * which closes the resource. * * In these situations, only one of the thrown exceptions can be * propagated. In the {@code try}-with-resources statement, when * there are two such exceptions, the exception originating from * the {@code try} block is propagated and the exception from the * {@code finally} block is added to the list of exceptions * suppressed by the exception from the {@code try} block. As an * exception unwinds the stack, it can accumulate multiple * suppressed exceptions. * * <p>An exception may have suppressed exceptions while also being * caused by another exception. Whether or not an exception has a * cause is semantically known at the time of its creation, unlike * whether or not an exception will suppress other exceptions * which is typically only determined after an exception is * thrown. * * <p>Note that programmer written code is also able to take * advantage of calling this method in situations where there are * multiple sibling exceptions and only one can be propagated. * * @param exception the exception to be added to the list of * suppressed exceptions * @throws IllegalArgumentException if {@code exception} is this * throwable; a throwable cannot suppress itself. * @throws NullPointerException if {@code exception} is {@code null} * @since 1.7 */ public final void addSuppressed(Throwable exception) /** * Returns an array containing all of the exceptions that were * suppressed, typically by the {@code try}-with-resources * statement, in order to deliver this exception. * * If no exceptions were suppressed or {@linkplain * Throwable(String, Throwable, boolean) suppression is disabled}, * an empty array is returned. This method is * thread-safe. Writes to the returned array do not affect future * calls to this method. * * @return an array containing all of the exceptions that were * suppressed to deliver this exception. * @since 1.7 */ public final Throwable[] getSuppressed() // Added explicit specification for readObject. /** * Reads a {@code Throwable} from a stream, enforcing * well-formedness constraints on fields. Null entries and * self-pointers are not allowed in the list of {@code * suppressedExceptions}. Null entries are not allowed for stack * trace elements. * * Note that there are no constraints on the value the {@code * cause} field can hold; both {@code null} and {@code this} are * valid values for the field. */ private void readObject(ObjectInputStream s) /** * Write a {@code Throwable} object to a stream. * * A {@code null} stack trace field is represented in the serial * form as a one-element array whose element is equal to {@code * new StackTraceElement("", "", null, Integer.MIN_VALUE)}. */ private void writeObject(ObjectOutputStream s) /** * The stack trace, as returned by {@link #getStackTrace()}. * The field is initialized to a zero-length array. A {@code * null} value of this field indicates subsequent calls to {@link * #setStackTrace(StackTraceElement[])} and {@link * #fillInStackTrace()} will be be no-ops. * * @serial * @since 1.4 private StackTraceElement[] stackTrace;
Three Throwable
subclasses in java.lang
have
a disclaimer added that their objects may be constructed by the
virtual machine as if suppression were disabled:
java.lang.ArithmeticException
java.lang.NullPointerException.java
java.lang.OutOfMemoryError.java
The language specification changes involve §14.20 "The try
statement," and will eventually introduce a new subsection
§14.20.3 "Execution of try
-with-resources," although
the specification presented below is not partitioned as such.
SYNTAX: The existing set of grammar productions for TryStatement in §14.20 is augmented with an alternative including resources:
try
Block Catches
try
Block Catchesopt Finally
try
ResourceSpecification Block Catchesopt Finallyopt
Supporting new grammar productions are added:
(
Resources ;
opt )
;
Resources=
Expression
A try
-with-resources statement has a resource
specification that declares resources to be automatically closed at
the end of the Block.
A resource specification declares one or more local variables; the
type of each variable must be a subtype of AutoCloseable
or a compile-time error occurs.
A variable must not have the same name as a variable declared earlier
in the resource specification, a local variable, or parameter of the
method or initializer block immediately enclosing the try
statement, or a compile-time error occurs.
The scope of a variable declared in a resource specification of a
try
-with-resources statement (§14.20) is from the
declaration rightward over the remainder of the resource specification
and the entire Block associated with the try
.
Within the Block of the try
, the name of the
variable may not be redeclared as a local variable of the directly
enclosing method or initializer block, nor may it be redeclared as an
exception parameter of a catch
clause in a
try
statement of the directly enclosing method or
initializer block, nor may it be redeclared as a variable in the
resource specification, or a compile-time error occurs.
However, a variable declared in a resource specification may be
shadowed (§6.3.1) anywhere inside
a class declaration nested within the Block of the
try
.
The meaning of a try
-with-resources statement with a
Catches clause or Finally block is given by translation
to a try
-with-resources statement with neither a
Catches clause nor a Finally block:
try
ResourceSpecification
Block
Catchesopt
Finallyopt
⇒
try {
try
ResourceSpecification
Block
}
Catchesopt
Finallyopt
After translation outward of any Catches clause or
Finally block to an outer try
, in a
try
-with-resources statement with no Catches
clause or Finally block that manages a single resource:
If the initialization of the resource completes abruptly because of a
throw of a value V, or if the Block of the
try
-with-resources statement completes abruptly because
of a throw of a value V and the automatic closing of the
resource completes normally, then the try
-with-resources
statement completes abruptly because of the throw of value V.
If the Block of the try
-with-resources
statement completes abruptly because of a throw of a value V1,
and the automatic closing of the resource completes abruptly because
of a throw of a value V2, then the
try
-with-resources statement completes abruptly because
of the throw of value V1 with V2 added to the suppressed
exception list of V1.
In a try
-with-resources statement that manages multiple resources:
If the initialization of a resource completes abruptly because of a
throw of a value V, or if the Block of the
try
-with-resources statement completes abruptly because
of a throw of a value V (which implies that the initialization
of all resources completed normally) and the automatic closings of all
initialized resources completes normally, then the
try
-with-resources statement completes abruptly because
of the throw of value V.
If the initialization of a resource completes abruptly because of a
throw of a value V1 and the automatic closings of one or more
resources (that were previously successfully initialized) complete
abruptly because of throws of values V2...Vn, then the
try
-with-resources statement completes abruptly because
of the throw of a value V1 with V2...Vn added to
the suppressed exception list of V1.
If the Block of the try
-with-resources statement
completes abruptly because of a throw of a value V1,
and the automatic closings of one or more resources (that were
previously successfully initialized) complete abruptly because of
throws of values V2...Vn, then the
try
-with-resources statement completes abruptly because
of the throw of a value V1 with
V2...Vn added to the
suppressed exception list of V1.
The exceptions that can be thrown by a try
-with-resources
statement are the exceptions that can be thrown by the Block of
the try
-with-resources statement plus the union of the
exceptions that can be thrown by the automatic closing of the
resources themselves.
Regardless of the number of resources managed by a
try
-with-resources statement, it is possible for a
Catches clause associated with the statement to catch an
exception due to initialization or automatic closing of any resource.
A try
-with-resources statement with a
ResourceSpecification clause that declares multiple
Resources is treated as if it were multiple
try
-with-resources statements, each of which has a
ResourceSpecification clause that declares a single
Resource.
When a try
-with-resources statement with n
Resources (n > 1) is translated, the result
is a try
-with-resources statement with n-1
Resources.
After n such translations, there are n nested
try-catch-finally
statements, and the overall translation
is complete.
The meaning of a try
-with-resources statement with a
ResourceSpecification clause and no Catches clause or
Finally block is given by translation to a local variable
declaration and a try-catch-finally
statement.
During translation, if the ResourceSpecification clause
declares one Resource, then the try-catch-finally
statement is not a try
-with-resources statement, and
ResourceSpecificationtail is empty.
If the ResourceSpecification clause declares n > 1
Resources, then the try-catch-finally
statement is
treated as if it were a
try
-with-resources-catch-finally
statement,
where ResourceSpecificationtail is a
ResourceSpecification consisting of the 2nd,
3rd, ..., nth Resources in order.
The translation is as follows, where the identifiers
#primaryException
, #t
, and
#suppressedException
are fresh:
try
ResourceSpecification
Block
⇒
{
final
VariableModifiers_minus_final R#resource =
Expression;
Throwable #primaryException = null;
try
ResourceSpecificationtail
Block
catch (Throwable #t) {
#primaryException = t;
throw #t;
} finally {
if (#resource != null) {
if (#primaryException != null) {
try {
#resource.close();
} catch(Throwable #suppressedException) {
#primaryException.addSuppressed(#suppressedException);
}
} else {
#resource.close();
}
}
}
}
The value of VariableModifiers_minus_final is the set of
modifiers on the variable (except for final
, if present);
R is the type of the variable declaration; and
#resource
is the name of the variable declared in the
Resource.
The close
method is only called on a resource if the
resource is initialized to a non-null
value.
The reachability and definite assignment rules for the
try
statement with a resource specification are
implicitly specified by the translations above.
Discussion: The
Throwable.printStackTrace
family of methods have their expected behavior updated to include displaying information about suppressed exceptions.An implication of the combined grammar is that a
try
statement must have at least one of acatch
clause, afinally
block, and a resource specification. Furthermore, it is permissible for atry
statement to have exactly one of these three components.The grammar for a declared resource is
VariableModifiersopt Type VariableDeclaratorId=
Expression
rather than the simpler LocalVariableDeclaration
to disallow code like
AutoCloseable a, b, c
which is not useful in this context since the variables have to be initialized. A suggested grammatical extension has been to allow multiple resources to share the declared resource type as in// Suggested syntax extension try(Resource r0 = new Resource(), // Comma separating resources r1 = new Resource()) { // with a shared type //... }However, this has been judged to be a change with low utility since managing multiple resource of the same type is expected to be relatively uncommon. In many cases where multiple resources are managed, one resource is a wrapper around an underlying resource.
The exception behavior of
close
methods is accounted for in determining the set of exceptions atry
-with-resources statement can throw.By design, no special accommodations are made to deal with the
ThreadDeath
error which is spawned by the long-deprecatedThead.stop
method.Resource declarations in a resource specification are implicitly
final
. For consistency with existing declarations that have implicit modifiers, it is legal (though discouraged) for a programmer to provide an explicit "final
" modifier. By allowing non-final
modifiers, annotations such as@SuppressWarnings
will be preserved on the translated code, which implies@SuppressWarnings
on a resource will have the intended effect.Unlike the fresh identifier in the translation of the enhanced-
for
statement, the#resource
variable is in scope in the Block of atry
-with-resources statement.The translation exploits the improved precision of exception analysis for an effectively
final
exception parameter.At least in Java SE 7, a class must have a method named "close" to implement the
AutoCloseable
interface and thus work with thetry
-with-resources statement. To allow methods with other names like "dispose" to be called at block exit instead, an adapter interface with a matching factory can be used to wrap the object in question and forward calls from "close" to the type-specific clean-up method. In the future, it is possible other mechanisms, such as interface injection, may also allow classes not declared to implementAutoCloseable
to be operated on by thetry
-with-resources statement
JLSv3 mandates many uninformative unchecked warning messages be generated by compilers when certain potentially problematic varargs methods are called. The set of methods considered problematic in this way includes methods in the core JDK libraries. This feature generates a new warning at the declaration of such methods and provides a mechanism for the programmer to state the method is actually not problematic so that warnings are not generated at either the method's declaration or use.
As part of this language change, an unchecked warning is required at declaration sites of varargs methods and constructors that have a non-reifiable element type (JLSv3 §4.7) for the varargs parameter. Previously, call sites of such methods have generated unchecked warnings. The requirement is specified by adding a sentence to JLSv3 §8.4.1 "Formal Parameters":
If the last formal parameter is a variable arity parameter of type T,
it is considered to define a formal parameter of type T[].
The method is then a variable arity method.
Otherwise, it is a fixed arity method.
If T is a non-reifiable type (§4.7), then the declaration
of the variable arity method generates a compile-time unchecked
warning (§4.12.2.1) unless the
unchecked warning is suppressed by the method being annotated with a
@SafeVarargs
annotation (reference to new subsection
in §9.6.1).
Invocations of a variable arity method may contain more actual
argument expressions than formal parameters.
All the actual argument expressions that do not correspond to the
formal parameters preceding the variable arity parameter will be
evaluated and the results stored into an array that will be passed to
the method invocation (§15.12.4.2).
A new subsection is added to the Predefined Annotation Types section
of JLSv3, (§9.6.1), to
describe SafeVarargs
:
SafeVarargs
A variable arity parameter with a non-reifiable element type (§4.7) can cause heap pollution (§4.12.2.1) and associated unchecked warnings. Such warnings are uninformative if the body of the variable arity method is well-behaved with respect to the variable arity parameter. The annotation type
SafeVarargs
, when used to annotate a method or constructor, makes a programmer assertion which prevents the compiler from reporting unchecked warnings for the declaration or invocations of a variable arity method or constructor where the compiler would otherwise do so due to the variable arity parameter having a non-reifiable element type.It is a compile-time error if a fixed-arity method or constructor is annotated with the
@SafeVarargs
annotation. It is a compile-time error if a variable-arity method that is neitherstatic
norfinal
is annotated with the@SafeVarargs
annotation.
The documentation of the new SafeVarargs
annotation type is below.
Annotation Type SafeVarargs
@Documented @Retention(value=RUNTIME) @Target(value={CONSTRUCTOR,METHOD}) public @interface SafeVarargsA programmer assertion that the body of the annotated method or constructor does not perform potentially unsafe operations on its varargs parameter. Applying this annotation to a method or constructor suppresses unchecked warnings about a non-reifiable variable-arity (vararg) type and suppresses unchecked warnings about parameterized array creation at call sites.
In addition to the usage restrictions imposed by its
@Target
meta-annotation, compilers are required to implement additional usage restrictions on this annotation type; it is a compile-time error if a method or constructor declaration is annotated with a@SafeVarargs
annotation, and either:
- the declaration is a fixed-arity method or constructor
- the declaration is a variable-arity method that is neither
static
norfinal
.Compilers are encouraged to issue warnings when this annotation type is applied to a method or constructor declaration where:
- The variable-arity parameter has a reifiable element type, which includes primitive types,
Object
, andString
. (The unchecked warnings this annotation type suppresses already do not occur for a reifiable element type.)- The body of the method or constructor declaration performs potentially unsafe operations, such as an assignment to an element of the variable-arity parameter's array that generates an unchecked warning. Some unsafe operations do not trigger an unchecked warning. For example, the aliasing in
leads to a@SafeVarargs // Not actually safe! static void m(List<String>... stringLists) { Object[] array = stringLists; List<Integer> tmpList = Arrays.asList(42); array[0] = tmpList; // Semantically invalid, but compiles without warnings String s = stringLists[0].get(0); // Oh no, ClassCastException at runtime! }ClassCastException
at runtime.Future versions of the platform may mandate compiler errors for such unsafe operations.
The platform methods and constructors annotated with a
@SafeVarargs
annotation are:
public static <T> List<T> java.util.Arrays.asList(T... a)
public static <T> boolean java.util.Collections.addAll(Collection<? super T> c, T... elements)
public static <E extends Enum<E>> java.util.EnumSet<E> EnumSet.of(E first, E... rest)
protected final void javax.swing.SwingWorker.publish(V... chunks)
Discussion: The non-local effect of a
@SafeVarags
annotation suppressing warnings at call sites (in addition to the declaration site) differs from the effects of a@SuppressWarnings
annotation on a declaration.The canonical target for a
@SafeVarargs
annotation is a method likejava.util.Collections.addAll
, whose declaration starts withpublic static <T> boolean java.util.Collections.addAll(Collection<? super T> c, T... elements)The varargs parameter has underlying type
T[]
, which is non-reifiable. However, the method fundamentally just reads from the input array and adds the elements to a collection, which is a safe operation with respect to the array. Therefore the unchecked warnings at call sites ofCollections.addAll
are arguably spurious and uninformative. Applying a@SafeVarargs
annotation to the method stops generation of these unchecked warnings at the methods' call sites.In practice, the
EnumSet.of
method should not generate unchecked warnings since the inferred type in any given application of the method should be some particular concrete enum type. This is a consequence of the additional restrictions imposed on enum types, such as they are all direct subclasses of the abstract classjava.lang.Enum
. However, adding@SafeVarargs
does correctly capture the semantics of the method.Generally safe operations on the varargs parameter include only reading from the parameter and treating the parameter in an invariant sense. Aliasing the parameter is potentially unsafe.
Since new unchecked warnings are being introduced, those diligently compiling with options like "
-Xlint:unchecked -Werror
" will see a build error under JDK 7 if any of the suspicious varargs method declarations are found. To address this, the@SafeVarargs
annotation can be applied to the declarations, if appropriate, or in the compiler reference implementation the@SuppressWarnings({"unchecked", "varargs"})
annotation can be applied. Unlike@SafeVarargs
, the@SuppressWarnings
annotation will not squelch unchecked warnings at the call sites of the annotated method.Since a
@SafeVarargs
annotation is only applicable tostatic
methods,final
instance methods, and constructors, the annotation is not usable in a situation where method overriding occurs. Annotation inheritance only works on classes (not methods, interfaces, or constructors) so without changing annotation inheritance, aSafeVarargs
-style annotation cannot be passed through general instance methods in classes or through interfaces.Since it affects programming language semantics, the
SafeVarargs
annotation type is placed in thejava.lang
package.The
SafeVarargs
annotation type is declared with a runtimeRetentionPolicy
for several reasons. Some representation of theSafeVarargs
status is needed in class files to allow compilers to know to omit unchecked warnings at call sites of annotated methods, unchecked warnings that would otherwise be mandated by the language specification. If this information is stored using an annotation, the annotation type can have one of three retention policies, SOURCE, CLASS, or RUNTIME. With the SOURCE policy, the annotation would not be stored in the class file at all, which would not meet the requirements of eliding warnings when uses of the annotated method or constructor are compiled separately from the class declaring the method or constructor. That leaves CLASS and RUNTIME as potential retention policies. Both policies use equal space in the class file. However, an advantage of RUNTIME retention is that no explicit method is needed in reflective APIs to query theSafeVarargs
status of a method or constructor since the presence or absence of the annotation can be tested. For example, there is no need for anisSafeVarargs
method on theMethod
andConstructor
classes in thejava.lang.reflect
package or for anisSafeVarargs
method injavax.lang.model.element.ExecutableElement
. Therefore, theSafeVarargs
annotation type is declared with RUNTIME retention and no methods are added to any of the platform's reflective APIs to query for this information. This information could conceivably be stored in a new class file attribute, but small language changes do not change the VM specification and a new recognized class file attribute is a VM change. An additional benefit of having the information in class files is enabling class file-based analysis tools to perform additional checks on the operations of annotated methods and constructors.
Forbid combining diamond and explicit type arguments to a generic constructor.
Removed unusual protocol around
Throwable.addSuppressed(null)
and added a new constructor
to Throwable
to allow suppression to be disabled.
Added disclaimers that OutOfMemoryError
,
NullPointerException
, and ArithmeticException
objects created by the JVM may have suppression disabled.
Added thread safely requirements to
Throwable.addSuppressed
and
Throwable.getSuppressed
Strong warnings were added to the javadoc of
AutoCloseable
about having the close
method
throw InterruptedException
.
Various small improvements and clarifications.
The JSR 269 language model follows somewhat different evolution rules than most APIs included in Java SE. In particular, while the changes to the API are binary compatible, certain source incompatible changes are made of necessity. In particular, methods have been added to the visitor interfaces to allow operations on newly-added language constructs to be performed. This evolution path was expected during JSR 269's development and for that reason, developers were warned to not directly implement the visitor interfaces, but rather to extend one of the visitor utility classes. The utility classes are versioned per release and implement default behavior appropriate for that release.
Changes to the language model include:
New enum constant
javax.lang.model.SourceVersion.RELEASE_7
.
In the package description of
javax.lang.model.element
, requirements on when a model
must be provided are loosened to remove the requirement in case of an
"irrecoverable error that could not be removed by the generation of
new types," a condition which includes but is not limited to syntax
errors.
New exception type
javax.lang.model.UnknownEntityException
added as a common
superclass for existing exception types
UnknownAnnotationValueException
,
UnknownElementException
, and
UnknownTypeException
.
New enum constant
javax.lang.model.element.ElementKind.RESOURCE_VARIABLE
.
New mixin interfaces Parameterizable
and
QualifiedNameable
added to package
javax.lang.model.element
.
ExecutableElement
and TypeElement
are
retrofitted to extend Parameterizable
;
PackageElement
and TypeElement
are
retrofitted to extend QualifiedNameable
.
Behavior of getEnclosingElement
method defined to
return the generic element of a type parameter instead of
null
.
New interface
javax.lang.model.type.UnionType
to model
union types.
New enum constant
javax.lang.model.type.TypeKind.UNION
to mark
union types.
New method visitUnion
added to visitor
interface javax.lang.model.type.TypeVisitor
.
Utility visitor implementations updated accordingly.
In the package javax.lang.model.type
,
MirroredTypesException
retrofitted to be the
superclass of MirroredTypeException
.
New utility visitors for release 7 in package
javax.lang.model.util
:
AbstractAnnotationValueVisitor7
AbstractElementVisitor7
AbstractTypeVisitor7
ElementKindVisitor7
ElementScanner7
SimpleAnnotationValueVisitor7
SimpleElementVisitor7
SimpleTypeVisitor7
TypeKindVisitor7
The visitors ElementKindVisitor6
,
ElementScanner6
, and SimpleElementVisitor6
,
are updated to account for new element kind
RESOURCE_VARIABLE
.
The visitor AbstractTypeVisitor6
is updated to
account for the possibility of visiting a
UnionType
.
Definition of documentation comment added to javadoc of
javax.lang.model.util.Elements.getDocComment
.