JDK-7015422 : 15.9: Constructor 'throws' clause with type variable is not specified in class instance creation expression
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 6u22
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2011-01-27
  • Updated: 2015-11-09
  • Resolved: 2015-11-09
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 8
8Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
15.9 says the thrown types of a class instance creation expression include E, where "E is listed in the throws clause of the type of the constructor that is invoked".  This doesn't account for the possibility that E may be a type variable (one of the type parameters of the constructor).

The text needs to be clarified, and 15.9.3 in particular needs to describe how the throws clause may be derived from inferred type arguments.  It's particularly unclear whether E should be erased due to unchecked argument conversion, as in 15.12.2.6.

I believe the scope of this problem is restricted to the case of type variables appearing as thrown types.  8.1.2 prohibits exception classes from being generic, so we can never have throws MyException<T>, etc.

I wrote a test to see what implementations did.  The results demonstrate that the correct behavior is very poorly understood.

/**
 * Testing the following from JLS 15.12.2.6:
 * If unchecked conversion was necessary for the method to be applicable
 * then the throws clause is composed of the erasure (4.6) of the types
 * in the method���s declared throws clause.
 */
public class UncheckedInvocation {

  static <E extends Exception> Iterable<E> empty(Iterable<E> arg) throws E {
    for (E e : arg) throw e;
    return arg;
  }

  <E extends Exception> UncheckedInvocation(Iterable<E> arg) throws E {
    empty(arg);
  }

  /**
   * Method invocation, no unchecked
   * Specified thrown: RuntimeException
   * javac: RuntimeException
   * Eclipse: RuntimeException
   */
  void m1() {
    Iterable<RuntimeException> i = java.util.Collections.emptyList();
    empty(i);
  }

  /**
   * Method invocation, unchecked, inferred arguments
   * Specified thrown: Exception
   * javac: E (!)
   * Eclipse: Exception
   */
  void m2() {
    Iterable i = java.util.Collections.EMPTY_LIST;
    empty(i);
  }

  /**
   * Method invocation, unchecked, explicit arguments
   * Specified thrown: Exception
   * javac: RuntimeException
   * Eclipse: RuntimeException
   */
  void m3() {
    Iterable i = java.util.Collections.EMPTY_LIST;
    UncheckedInvocation.<RuntimeException>empty(i);
  }

  /**
   * Constructor invocation, no unchecked
   * Specified thrown: RuntimeException (unclear)
   * javac: E (!)
   * Eclipse: RuntimeException
   */
  void m4() {
    Iterable<RuntimeException> i = java.util.Collections.emptyList();
    new UncheckedInvocation(i);
  }

  /**
   * Constructor invocation, unchecked, inferred arguments
   * Specified thrown: Exception? (unclear)
   * javac: E (!)
   * Eclipse: Exception
   */
  void m5() {
    Iterable i = java.util.Collections.EMPTY_LIST;
    new UncheckedInvocation(i);
  }

  /**
   * Constructor invocation, unchecked, explicit arguments
   * Specified thrown: Exception? (unclear)
   * javac: E (!)
   * Eclipse: RuntimeException
   */
  void m6() {
    Iterable i = java.util.Collections.EMPTY_LIST;
    new <RuntimeException>UncheckedInvocation(i);
  }

}

Comments
Note that the reference to 15.9 in the bug report, "E is listed in the throws clause of the type of the constructor that is invoked", has been moved and modified in JLS 8. Now it is found in 11.2.1: "E is one of the exception types of the invocation type of the chosen constructor (��15.12.2.6)"
24-09-2015

JDK-8034925 raises the broader issue of how 15.9 maps to 15.12. If we get the mapping right, then 15.12.2.6 (as revised in JLS 8) should handle exception types correctly.
31-07-2014

PUBLIC COMMENTS I've created 7015430 for the compiler bugs. I discovered that the 7 compiler no longer leaks a type variable out of scope in the explicit argument case, but it still fails to choose the erasure of the variable as the thrown type (instead, it matches Eclipse in this case).
27-01-2011