JDK-8073593 : 15.9: Allow diamond to be used with anonymous classes
  • Type: Sub-task
  • Component: specification
  • Sub-Component: language
  • Affected Version: 8
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2015-02-20
  • Updated: 2018-08-03
  • Resolved: 2016-09-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
As part of JEP 213, we'd like to relax the restriction that "If the class instance creation expression ends in a class body ... [and] TypeArgumentsOrDiamond is present after the Identifier, and denotes <>, then a compile-time error occurs."

Instead, this should be allowed in general, but we must check after inference that the inferred type arguments can be expressed in the generated class file's Signature attribute.  (I.e., no capture variables, no intersections, etc.)
Comments
Static methods cannot be declared in anonymous classes (8.1.3). But it doesn't hurt to use the phrase "non-private instance methods" in order to avoid confusion.
16-12-2015

Since static methods never override anything, it is right to exclude static methods from "as if annotated with @Override" in the class body. In addition, JLS8 9.6.4.4's rule for @Override -- "If a method declaration is annotated with the annotation @Override, but the method does not override or implement a method declared in a supertype, or is not override-equivalent to a public method of Object, a compile-time error occurs." -- is deficient because it uses the pre-JLS8 "implements" terminology and does not use the JLS8 "overrides from ..." terminology. Also, given the possibility of using @Override on default methods in an interface hierarchy, it would be proper to allude to interfaces as well as classes. Suggestion: "If a method declaration in type T is annotated with the annotation @Override, but the method does not _override from T_ a method declared in a supertype of T, or is not override-equivalent to a public method of Object, a compile-time error occurs."
11-11-2015

***If the class instance creation expression elides the supertype's type arguments using '<>', then for all non-private methods declared in the class body, it is as if the method declaration is annotated with @Override (9.6.4.4).*** Do we want to say: all non-private instance methods declared in the class body ... ? ATM, javac gives an error for static methods also.
11-11-2015

Settled text for 15.9.3: Second, a constructor of C and corresponding return type and throws clause are determined: [BEGIN FIRST BULLET] If the class instance creation expression uses '<>' to elide class ***or interface*** type arguments, a list of methods m1...mn is defined for the purpose of overload resolution and type argument inference. ***If C is an anonymous class, let D be the superclass or superinterface of C named by the class instance creation expression. Otherwise, let D be the same as C.*** Let c1...cn be the constructors of class ***D, or if D is an interface, a singleton list containing the zero-argument constructor of class Object***. Let #m be an automatically generated name that is distinct from all constructor and method names in ***D***. For all j (1 ��� j ��� n), 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 ***D***, and let G1...Gq be the type parameters (if any) of cj. Let X1...Xp and Y1...Yq be type variables with distinct names that are not in scope in the body of ***D***. ��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 ***D*** or cj. - The return type of mj is ��j applied to ***D***<F1,...,Fp>. ��� The name of mj is #m. ��� 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...mn to be members of ***D***. Then one of m1...mn is selected, as determined by the class instance creation's argument expressions, using the process specified in ��15.12.2. If there is no unique most specific method that is both applicable and accessible, then a compile-time error occurs. Otherwise, where mj is the selected method: ***If C is not an anonymous class, then*** cj is the chosen constructor. The return type and throws clause of cj are the same as the return type and throws clause determined for mj (��15.12.2.6). ***If C is an anonymous class, then the chosen constructor is the constructor of the anonymous class. The return type is the anonymous class type.*** ***The selection of cj impacts the anonymous class declaration as follows: - The superclass or superinterface type of the anonymous class is the return type, T, determined for mj (15.12.2.6). - The 'super(...)' call in the anonymous class constructor invokes cj; the 'throws' clause of the anonymous class constructor includes the exceptions in the 'throws' clause determined for mj (15.9.5.1).*** ***It is a compile-time error if the superclass or superinterface type of the anonymous class, T, or any subexpression of T, has one of the following forms: - A type variable (4.4) that was not declared as a type parameter (such as a type variable produced by capture conversion (5.1.10)) - An intersection type (4.9) - A class or interface type, where the class or interface declaration is not accessible from the class or interface in which the expression appears. The term "subexpression" includes type arguments of parameterized types (4.5), bounds of wildcards (4.5.1), and element types of array types (10.1). It excludes bounds of type variables.*** [Motivation: This is consistent with 15.27.3, "It is a compile-time error if any class or interface mentioned by either U or the function type of U is not accessible from the class or interface in which the lambda expression appears."] [BEGIN SECOND BULLET] Otherwise, the class instance creation expression does not use <> to elide class ***or interface*** type arguments. ***If C is not an anonymous class,*** let T be the type denoted by C followed by any class type arguments in the expression. The process specified in ��15.12.2, modified to handle constructors, is used to select one of the constructors of T and determine its throws clause. If there is no unique most-specific constructor that is both applicable and accessible, then a compile-time error occurs (as in method invocations). Otherwise, the return type is T. [The following is mostly a bug fix. The existing text, above, is not strictly correct when applied to anonymous classes.] ***If C is an anonymous class, the process specified in 15.12.2, modified to handle constructors, is used to select one of the constructors of the direct superclass of C and determine its throws clause.*** ***If there is no unique most-specific constructor that is both applicable and accessible, then a compile-time error occurs (as in method invocations).*** ***Otherwise, the 'super(...)' call in the anonymous class constructor invokes the selected constructor; the 'throws' clause of the anonymous class constructor includes the exceptions in the 'throws' clause determined for the selected constructor (15.9.5.1).*** ***The selected constructor of the class instance creation expression is the anonymous class constructor; the return type is the anonymous class type.*** It is a compile-time error if an argument to a class instance creation expression is not compatible with its target type, as derived from the invocation type (��15.12.2.6). If the compile-time declaration is applicable by variable arity invocation (��15.12.2.4), then where the last formal parameter type of the invocation type of the constructor is Fn[], it is a compile-time error if the type which is the erasure of Fn is not accessible at the point of invocation. The type of the class instance creation expression is the return type of the chosen constructor, as defined above. ***[Delete; has become redundant:] Note that the type of the class instance creation expression may be an anonymous class type, in which case the constructor being invoked is an anonymous constructor (��15.9.5.1).***
12-09-2015

Settled text for 15.9.5 (including 15.9.5.1): 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 always implicitly final (��8.1.1.2). 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 type is given by the class instance creation expression (15.9.1); if this type is generic and its type arguments are elided using '<>', the type arguments are inferred while choosing a constructor (15.9.3).*** ***If the class instance creation expression elides the supertype's type arguments using '<>', then for all non-private methods declared in the class body, it is as if the method declaration is annotated with @Override (9.6.4.4).*** ***[Note:] When the diamond form 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 actually annotated with @Override) helps avoid silently incorrect programs.*** 15.9.5.1 Anonymous Constructors An anonymous class cannot have an explicitly declared constructor. Instead, an anonymous constructor is implicitly declared for an anonymous class. The form of the anonymous constructor for an anonymous class C with direct superclass S is as follows: - If S is not an inner class, or if S is a local class that occurs in a static context,then the anonymous constructor has one formal parameter for each actual argument to the class instance creation expression in which C is declared. The actual arguments to the class instance creation expression are used to determine a constructor cs of S ***as described in 15.9.3***. The type of each formal parameter of the anonymous constructor must be identical to the corresponding formal parameter of cs. The constructor body consists of an explicit constructor invocation (��8.8.7.1) ***as if by*** the form 'super(...)', where the actual arguments are the formal parameters of the constructor, in the order they were declared. ***The superclass constructor to be invoked is cs.*** - Otherwise, the first formal parameter of the constructor of C represents the value of the immediately enclosing instance of i with respect to S (��15.9.2, ��15.9.3). The type of this parameter is the class type that immediately encloses the declaration of S. The constructor has an additional formal parameter for each actual argument to the class instance creation expression that declared the anonymous class. The n'th formal parameter e corresponds to the n-1'th actual argument. The actual arguments to the class instance creation expression are used to determine a constructor cs of S ***as described in 15.9.3***. The type of each formal parameter of the anonymous constructor must be identical to the corresponding formal parameter of cs. The constructor body consists of an explicit constructor invocation (��8.8.7.1) ***as if by*** the form 'o.super(...)', where o is the first formal parameter of the constructor, and the actual arguments are the subsequent formal parameters of the constructor, in the order they were declared. ***The superclass constructor to be invoked is cs.*** In all cases, the throws clause of an anonymous constructor must list all the checked exceptions thrown by ***cs, as determined in 15.9.3***, and all checked exceptions thrown by any instance initializers or instance variable initializers of the anonymous class. Note that it is possible for the signature of the anonymous constructor to refer to an inaccessible type (for example, if such a type occurred in the signature of the superclass constructor cs). This does not, in itself, cause any errors at either compile-time or run-time.
11-09-2015

Updated spec for 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 unqualified: The Identifier after the new token must denote a class that is accessible, non- final, and not an enum type; or denote an interface that is accessible. Otherwise a compile-time error occurs. ***[Delete this sentence:] If TypeArgumentsOrDiamond is present after the Identifier, and denotes '<>', then a compile-time error occurs.*** Let T be the type denoted by 'Identifier [TypeArgumentsOrDiamond]' after the new token. If TypeArguments is present after the Identifier, then T must denote a well-formed parameterized type (��4.5), or a compile-time error occurs. If ***'Identifier' refers to*** a class, ***C***, then an anonymous direct subclass of ***C*** is declared. ***The type arguments to C, if any, are given by [TypeArgumentsOrDiamond], or, if this denotes '<>', will be inferred in 15.9.3.*** The body of the subclass is the ClassBody given in the class instance creation expression. ***If 'Identifier' refers to an interface, I, then an anonymous direct subclass of 'Object' that implements I is declared. The type arguments to I, if any, are given by [TypeArgumentsOrDiamond], or, if this denotes '<>', will be inferred in 15.9.3. The body of the anonymous class is the ClassBody given in the class instance creation expression.*** [Aside: these details of the anonymous class declaration may be more appropriate in 15.9.5. As is, it's kind of hard to find them.] The class being instantiated is the anonymous subclass. - If the class instance creation expression is qualified: The Identifier after the new token must unambiguously denote an inner class, ***C,*** that is accessible, non-final, not an enum type, and a member of the compile-time type of the Primary expression or the ExpressionName. Otherwise, a compile- time error occurs. ***[Delete this sentence:] If TypeArgumentsOrDiamond is present after the Identifier, and denotes '<>', then a compile-time error occurs.*** Let T be the type denoted by Identifier [TypeArgumentsOrDiamond] after the new token. If TypeArguments is present after the Identifier, then T must denote a well-formed parameterized type, or a compile-time error occurs. An anonymous direct subclass of ***C*** is declared. ***The type arguments to C, if any, are given by [TypeArgumentsOrDiamond], or, if this denotes '<>', will be inferred in 15.9.3.*** The body of the subclass is the ClassBody given in the class instance creation expression. The class being instantiated is the anonymous subclass.
23-02-2015