Non generic constructor thrown type (class type variable) is not erased despite of unchecked conversion
Georgiy Rakov
georgiy.rakov at oracle.com
Fri Aug 28 13:02:43 UTC 2015
Hello,
let's consider following example.
class MyException extends Exception {}class MyDerivedException
extends MyException {}class MyType<T> {MyType(T t) {}}public class
Test31 {public static void test() {try {MyDerivedException e1 = new
MyDerivedException();Foo foo = new Foo<MyDerivedException>(e1, new
MyType(""));} catch (MyDerivedException e2) {}}}class Foo<E1 extends
MyException> {public Foo(E1 e, MyType<String> a) throws E1 {throw e;}}
It compiles successfully on JDK9b78. Now let's consider reasoning
presented below.
1. According to following assertion, 15.12.2 is used in order to
determine the constructor thrown types:
***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*_/ [jls-15.9.3-120-B.1
<https://wiki.se.oracle.com/display/JPG/Coverage+of+diamond+with+anonymous+classes+feature#Coverageofdiamondwithanonymousclassesfeature-jls-15.9.3-120-B.1>]
2. According to my understanding the types in throws clause are
determined in the last subsection of 15.12.2, that is in 15.12.2.6,
which states:
If the chosen method is not generic, then [jls-15.12.2.6-100-C
<https://baloo.ru.oracle.com/jenkins/job/jck9-lang/lastSuccessfulBuild/artifact/build/out/htmlout/jls-15.html#jls-15.12.2.6-100-C>]:
If /_*unchecked conversion*_/ was necessary for the method to be
applicable, the parameter types of the invocation type are the
parameter types of the method's type, and the return type and
/_*thrown types*_/ are given by the erasures of the return type and
thrown types of the method's type [jls-15.12.2.6-100-C-A
<https://baloo.ru.oracle.com/jenkins/job/jck9-lang/lastSuccessfulBuild/artifact/build/out/htmlout/jls-15.html#jls-15.12.2.6-100-C-A>].
3. So unchecked conversion is necessary in order for the constructor to
be applicable because expression 'new MyType("")' of a raw type is
passed to parameterized parameter 'MyType<String> a'.
Could you please tell if I understand correctly that JLS implies that
when erasing constructor thrown types, the actual type which is erased
is not E1 but E1 with following substitution applied [E1 :=
MyDerivedException]. According to my understanding JLS doesn't specify
this explicitly, but as I see it such clarification could be useful.
Could you please also tell if you think it's worth filing P4 issue about
this.
Thank you,
Gosha.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20150828/00feb6ad/attachment-0001.html>
-------------- next part --------------
class MyException extends Exception {}
class MyDerivedException extends MyException {}
class MyType<T> {
MyType(T t) {}
}
public class Test31 {
public static void test() {
try {
MyDerivedException e1 = new MyDerivedException();
Foo foo = new Foo<MyDerivedException>(e1, new MyType(""));
} catch (MyDerivedException e2) {
}
}
}
class Foo<E1 extends MyException> {
public Foo(E1 e, MyType<String> a) throws E1 {
throw e;
}
}
More information about the compiler-dev
mailing list