Name: rmT116609 Date: 09/22/2004
FULL PRODUCT VERSION :
java version "1.5.0-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-rc-b63)
Java HotSpot(TM) Client VM (build 1.5.0-rc-b63, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Linux router 2.6.8.1 #1 Mon Aug 16 23:49:22 CEST 2004 i686 athlon i386 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
There is no way to efficently create generic arrays without compiler warnings.
Compiler messages are used to indicate that some source code should be changed (e.g. due to a error). After the change, the compiler warning is not issued anymore. For the creation of generic arrays, no such change is available.
Additionally, the reasoning in http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf , page 15, is not quite exact:
A creation of an array of a generic type is not dangerous by itself, if it is just just to set or get elements of that generic type. The danger exists only if the compiler is not able to track the intended generic type of a concrete array. Thus, in the example provided by the generics tutorial,
List<String>[] lsa = new List<String>[10];
Object o = lsa;
not the first line should result in a compile time error, but the second line should. This is, because the generic array type List<String>[] is implicitly casted to the non-generic non-array type Object. (This is the only non-array type one can cast an array to.) It is due to the cast, that the compiler cannot track what the intended type of the generic array is, not because a generic array can exist in general. There should never be any warnings or error message issued for cases, where invariants (e.g. the generic type of an array element) can be proven to hold.
n
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the source code provided with
(1)
javac com/mn/tools/test/bugs/java/GenericArrayTest.java
(2)
javac -Xlint:unchecked com/mn/tools/test/bugs/java/GenericArrayTest.java
(3)
javac -Xlint:-unchecked com/mn/tools/test/bugs/java/GenericArrayTest.java
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
(1)
<empty message>
(2)
com/mn/tools/test/bugs/java/GenericArrayTest.java:15: warning: [unchecked] unchecked cast
found : java.lang.Object[]
required: T[]
return (T[]) new Object[size];
^
1 warning
(3)
<empty message>
ACTUAL -
(1)
Note: com/mn/tools/test/bugs/java/GenericArrayTest.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
(2)
com/mn/tools/test/bugs/java/GenericArrayTest.java:15: warning: [unchecked] unchecked cast
found : java.lang.Object[]
required: T[]
return (T[]) new Object[size];
^
1 warning
(3)
Note: com/mn/tools/test/bugs/java/GenericArrayTest.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
/** GenericArrayTest.java
*/
package com.mn.tools.test.bugs.java;
/**
Tests for a compile without warning.
*/
public class GenericArrayTest<T> {
public T[] createAnArray(int size) {
// This results in error "generic array creation"
// return new T[size];
// This results in warning "warning: [unchecked] unchecked cast"
return (T[]) new Object[size];
}
}
// :indentSize=8:tabSize=8:
---------- END SOURCE ----------
(Incident Review ID: 311052)
======================================================================

Comments

EVALUATION
First, due to erasure, there is no way to create an array from a type
variable. The required type information is simply not available at
runtime. See rfe 5098163.
Secondly, whether or not the Generics Tutorial is exact is a matter of
opinion. The real problem is that arrays are not statically type
safe. This is due to the subtype relation that states that T[] is a
subtype of S[] if T is a subtype of S.
This means that we must either disallow creation of generic arrays or
give warnings in cases like:
List<String>[] ss = ...;
List<?>[] l1 = ss; // warning?
List[] l2 = ss; // warning?
Object[] os = ss; // warning?
Object o = ss; // warning?
Since we cannot implement creation of generic array (since the
required type information is not available at runtime), it is
forbidden. However you can always make an unchecked cast. In the
future it should be possible to suppress unchecked warnings. See rfe
4986256.
Generics are supposed to be statically type safe. However, in order
to interface with old code and to allow programs which cannot be
expressed type safely in the current language, we sometimes allow
unsafe expressions but give mandatory warnings (they are required by
the language specification). This means that we can give a type
safety guarantee:
"if your entire application has been compiled without unchecked
warnings using javac -source 1.5, it is type safe."
An example which demonstrates that why the GenericArrayTest is not
type safe:
GenericArrayTest<String> g = new GenericArrayTest<String>();
String[] ss = g.createAnArray(); // causes a ClassCastException
###@###.### 2004-09-28