The supertype of anonymous class is expected to be a raw type
Georgiy Rakov
georgiy.rakov at oracle.com
Tue Aug 4 16:08:42 UTC 2015
Hello Alex,
sorry for the mistakes made.... but it seems another one has been
made..... that is assertion I specified in step 1 covers
diamond-expression-cases only, namely this assertion:
- The superclass or superinterface type of the anonymous class is
the return type, T, determined for mj (15.12.2.6).
but the original example provided type arguments instead; so the
consequent steps (that is all of them) were wrong and according to
following assertions
<https://bugs.openjdk.java.net/browse/JDK-8073593?focusedCommentId=13622110&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13622110>
the supertypes of anonymous classes should be parameterized when type
arguments for class are provided:
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.***
.... it seems it's better to continue this thread because of the mess
having been discovered; and thanks, I've taken into account the issues
you found in my original letter .....
So the conclusion I made earlier seems to be wrong now. However it looks
strange that, say, constructor invocation type, determines anonymous
class supertypes for diamond cases only. So could you please tell if
this is really the intention of the spec. For instance code below
outputs that just for diamond case anonymous class super class is not
parameterized:
When class type arguments are given, the super type is parameterized.
When class type arguments and ctor type arguments are given, the
super type is parameterized.
When diamond is used, the super type is /_*not*_/ parameterized.
The code:
import java.lang.reflect.ParameterizedType;
class MyType<T> {}
public class Test24 {
public static void main(String argv[]) {
Bar foo;
boolean isParameterized;
foo =new Bar<String>("str",new MyType()){ };
isParameterized = foo.getClass().getGenericSuperclass()instanceof ParameterizedType;
System.out.println("When class type arguments are given, the super type is " + (isParameterized?"":"not ") +"parameterized.");
foo =new <String>Bar<String>("str",new MyType()){ };
isParameterized = foo.getClass().getGenericSuperclass()instanceof ParameterizedType;
System.out.println("When class type arguments and ctor type arguments are given, the
super type is " + (isParameterized?"":"not ") +"parameterized.");
foo =new Bar<>("str",new MyType()){ };
isParameterized = foo.getClass().getGenericSuperclass()instanceof ParameterizedType;
System.out.println("When diamond is used, the super type is " + (isParameterized?"":"not ") +"parameterized.");
}
}
class Bar<T> {
public <U> Bar(T a1, MyType<U> a2){ }
}
Thanks, Georgiy.
On 03.08.2015 21:53, Alex Buckley wrote:
> Georgiy, Good analysis but you have a non-generic ctor in class Bar<T>
> (the class is generic but the ctor isn't). You also seem to say that
> the return type of the method derived from the ctor is MyType, but
> it's obviously Bar. I don't actually disagree with your conclusion
> since 15.12.2.6 would still give raw Bar as the return type for the
> non-generic ctor. But it would be helpful to clarify your mail and
> restart the thread. Alex On 8/3/2015 5:46 AM, Georgiy Rakov wrote:
>> Hello, let's consider following example:
>> importjava.lang.reflect.Type;
>> importjava.lang.reflect.ParameterizedType; classMyType<T> {}
>> public classTest22 { public static voidmain(String argv[])
>> { Bar foo =new<String>Bar<String>("str",newMyType()){ };
>> Type actualSuperType =
>> foo.getClass().getGenericSuperclass(); if(
>> actualSuperTypeinstanceofParameterizedType ) {
>> System.out.println("Parameterized"); } } }
>> classBar<T> { publicBar(Ta1, MyType<String> a2){ } }
>> When compiled and run by JDK9b75 "Parameterized" is printed. However
>> according to my understanding it shouldn't have to. The reasons for
>> this are presented below: 1. According to the following assertion
>> specified in JDK-8073593
>> <https://bugs.openjdk.java.net/browse/JDK-8073593?focusedCommentId=13612188&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13612188>
>> the superclass of anonymous class should be equal to the return type
>> of the method derived from Bar class constructor: - The
>> superclass or superinterface type of the anonymous class is the
>> return type, T, determined for mj (15.12.2.6). 2. The second actual
>> argument for the constructor is of a raw type MyType while the
>> corresponding formal parameter is a parameterized type
>> MyType<String>. So unchecked conversion is necessary in order for the
>> only Bar constructor to become applicable for the provided
>> invocation. 3. According to assertion presented above the return type
>> is determined by 15.12.2.6 which states following: * If the chosen
>> method is generic and the method invocation provides explicit
>> type arguments, let Pi be the type parameters of the method and
>> let Ti be the explicit type arguments provided for the method
>> invocation (1 ≤ i ≤ p). Then: o If unchecked conversion was
>> necessary for the method to be applicable, then the
>> invocation type's parameter types are obtained by applying
>> the substitution [P1:=T1, ..., Pp:=Tp] to the parameter types
>> of the method's type, and the invocation type's return type
>> and thrown types are given by the erasure of the return type
>> and thrown types of the method's type. Namely it says that the return
>> type of the invocation type is the erasure of the return type of the
>> method's type, provided unchecked conversion was necessary for the
>> method to be applicable. According to step 2 unchecked conversion was
>> necessary for the method to be applicable so the return type of the
>> method is the erasure of MyType<! T>, i .e. MyType. 4. So according
>> to step 1 given above the superclass of the anonymous class is MyType
>> which is a raw type, that is, it shouldn't not considered as a
>> parameterized one. 5. As a resultgetGenericSuperclass method should
>> return an instance of a class not implementing ParameterizedType
>> interface, but actually it returns an instance of a class
>> implementing ParameterizedType interface. Could you please tell if
>> you consider this as a bug. Please note that javap prints following
>> when it runs against anonymous class Test22$1: final class
>> Test22$1 extends *Bar<java.lang.String>* {
>> Test22$1(java.lang.String, MyType);} So if this is a bug it seems to
>> be javac bug. Thanks, Georgiy.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20150804/8740aaaa/attachment-0001.html>
-------------- next part --------------
import java.lang.reflect.ParameterizedType;
class MyType<T> {}
public class Test24 {
public static void main(String argv[]) {
Bar foo;
boolean isParameterized;
foo = new Bar<String>("str", new MyType()){ };
isParameterized = foo.getClass().getGenericSuperclass() instanceof ParameterizedType;
System.out.println("When class type arguments are given, the super type is " + (isParameterized? "": "not ") + "parameterized.");
foo = new <String>Bar<String>("str", new MyType()){ };
isParameterized = foo.getClass().getGenericSuperclass() instanceof ParameterizedType;
System.out.println("When class type arguments and ctor type arguments are given, the super type is " + (isParameterized? "": "not ") + "parameterized.");
foo = new Bar<>("str", new MyType()){ };
isParameterized = foo.getClass().getGenericSuperclass() instanceof ParameterizedType;
System.out.println("When diamond is used, the super type is " + (isParameterized? "": "not ") + "parameterized.");
}
}
class Bar<T> {
public <U> Bar(T a1, MyType<U> a2){ }
}
More information about the compiler-dev
mailing list