Community
Participate
Working Groups
the following code doesn't compile because inner is typed Foo<T>.Inner and not Foo.Inner. It's works with Foo<?>.Inner public class Foo<T> { private T t; private Foo.Inner[] inner; public Foo(T t) { this.t = t; inner = new Foo.Inner[10]; //Type mismatch: cannot convert from Foo.Inner[] to Foo<T>.Inner[] } private class Inner { } } Rémi Forax
If the Inner class is static, it works.
the following code with wildcard works in eclipse but not in javac (not permitted by the grammar ??) public class Foo<T> { private T t; private Foo<?>.Inner[] inner; public Foo(T t) { this.t = t; inner = new Foo<?>.Inner[10]; } private class Inner { } } Rémi Forax
I don't see why this would be forbidden by the grammar. new Foo<?>.Inner[10] can be seen as (I removed unused rules): ArrayCreationExpression: new ClassOrInterfaceType DimExprs Dimsopt where ClassOrInterfaceType is: ClassOrInterfaceType: ClassType ClassType: TypeDeclSpecifier TypeArgumentsopt TypeDeclSpecifier: TypeName ClassOrInterfaceType . Identifier TypeArguments: < ActualTypeArgumentList > ActualTypeArgumentList: ActualTypeArgument ActualTypeArgument: Wildcard Wildcard: ? WildcardBoundsOpt So new Foo<?>.Inner[10] is: 'new' ClassOrInterfaceType (ClassOrInterfaceType(TypeName('Foo') TypeArguments('<?>')) '.' Identifier('Inner')) DimExprs('[10]') It might not be semantically valid, but I think it should be syntactically valid.
Original problem only occurs in presence of array type ref: Foo.Inner[] due to bug in these reference resolution. Fixed in latest, releasing in 3.1.1 and 3.2 streams. Added GenericTypeTest#test810.
Actually, test is rather #test811
Also tuned unchecked warning diagnosis to properly report unchecked warning for: public class Foo<T> { private T t; private Foo<?>.Inner[] inner; public Foo(T t) { this.t = t; inner = new Foo.Inner[10]; } private class Inner { } } We were missing it since tolerating unbound enclosing parameterized type. Added GenericTypeTest#test812
Re: comment 2, I believe it should be rejected. Not syntactically, but rather since type Foo<?>.Inner isn't reifiable (JLS4.7), though the spec isn't quite explicit on this scenario. inner = new Foo<?>.Inner[10];
Added GenericTypeTest#test813 for latter case, and tuned #isReifiable() implementation to reject unbound parameterized enclosing types as well (only tolerate innermost to be unbound).
I'm not agree with you, array of non reifiable type are not rejected by the JLS. List<?>[] list=new ArrayList<?>[5]; is legal so Foo<?>.Inner[] inner = new Foo<?>.Inner[10]; is legal too.
I reply to myself, since my last post, i have read the JLS JLS 15.10 (page 426) : "An array creation expression creates an object that is a new array whose elements are of the type specified by the PrimitiveType or TypeName. It is a compiletime error if the TypeName does not denote a reifiable type (§4.7)" so TypeName must be a reifiable type. And in the footnote : "Note that the syntax ensures that the element type in an array creation expression cannot be a parameterized type, other than an unbounded wildcard." then array of parametrized type with unbonded wilcard is legal. JLS 4.7 "A type is reifiable if and only if one of the following holds: • It refers to a non-generic type declaration. • It is a parameterized type in which all type arguments are unbounded wildcards (§4.5.1). • It is a raw type (§4.8). • It is an array type (§10.1) whose component type is reifiable" using bullets 2 and 4, ArrayList<?> is a reifiable type. The JLS is not clear about the fact that if B is an inner-class of A and A<T> is a parametrized type then A<T>.B is a parametrized type. But JLS 4.5 (p66) give Seq<String>.Zipper<Integer> as an example of parametrized type. In summary : Foo<T>.Inner is a parametrized type (JLS 4.5) Foo<?>.Inner is a parameterized type in which all type arguments are unbounded wildcards (JLS 4.5.1) Foo<?>.Inner is a reifable type (JLS 4.7) new Foo<?>.Inner[10] is legal (JLS 15.10) so i think you can remove your patch.
A parameterized type has arguments, like List<String>. As you said, the spec 4.7 is not telling about the enclosing type case: Foo<?>.Inner I ping'ed spec lead for confirmation, and based on his answer I will advise. I will leave the change in for now, since it matches javac behavior for rejecting the code.
In case needing to tune the semantics for reifiable type, need to play with TypeBinding#isReifiable() and/or #needsUncheckedConversion().
From spec lead: Indeed, we've found that the definition of reifiable types does not handle nested types the way one would like. As the spec stands, your example is not reifiable. But it really should be. The exact definition needs to be worked out. Will correct the implementation of #isReifiable() accordingly.
Fixed
Verified in I20050921-0010 for 3.2M2
Verified using M20050923-1430 for 3.1.1