? extend T[] is not considered an array
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Feb 23 14:25:08 UTC 2024
Hi,
as currently specified, the type of the expression used in array access
must be an array type - see JLS 15.10.3
> The type of the array reference expression must be an array type (call
> it T|[]|, an array whose components are of type T), or a compile-time
> error occurs.
>
There is nothing in the JLS to suggest that an array type is anything
other than some type T followed by array brackets. E.g. in JLS 10.1:
> An array type is written as the name of an element type followed by
> some number of empty pairs of square brackets |[]|. The number of
> bracket pairs indicates the depth of array nesting.
>
So, javac is behaving as specified in the JLS. Note that wildcards are a
distraction here. The wildcard generates a captured type - that is a
type variable whose upper bound is an array type.
The following program:
```
class Foo<X extends Object[]> {
void test(X x) { Object o = x[0]; }
}
```
Exhibits the same behavior - e.g. it fails to compile, because "x" is
not an array.
So, the question you are asking is: why can't we assume that a
type-variable whose upper bound is an array type is also an array type?
This is discussed here:
https://bugs.openjdk.org/browse/JDK-8013843
My reading is that it's doable, but it's work to make sure that nothing
else gets affected. E.g. if we treat as array anything that has an array
supertype, then the "null type" might get tangled in the mix (e.g.
null[0]). Of course this is not a reason for not doing it - but some
care is required. For-each loops might be affected as well.
Cheers
Maurizio
On 13/01/2024 12:38, Attila Kelemen wrote:
> Hi,
>
> I have not found anything in JLS specifically mentioning this. So, I'm
> not sure if it is intentional, but the following code does not compile
> (in any versions of Java I have tried):
>
> ```
> interface ForEachable<T> {
> void forEach(Consumer<? super T> consumer);
> }
>
> List<String> wrongMethod(ForEachable<? extends String[]> arrays) {
> var result = new ArrayList<String>();
> arrays.forEach(array -> result.add(array[0]));
> return result;
> }
> ```
>
> or in an even simpler example:
>
> ```
> String first(Supplier<? extends String[]> supplier) {
> return supplier.get()[0];
> }
> ```
>
> The compiler complains about `array[0]` that `array` is not an array.
> While I get that the compiler cannot assume that there is no subtype
> of `String[]`, but even if there was one, I would expect it to be an
> array, and be indexable.
>
> An obvious workaround is to assign `array` to a new local variable,
> but it is awkward to do.
>
> Is this behavior a bug, or something required by the JLS?
>
> Thanks,
> Attila
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20240223/896d8a0e/attachment.htm>
More information about the compiler-dev
mailing list