So I know that you cannot \"easily\" create an array of a generic type in Java (but you can create collections). I recently ran across a situation where I needed a 2 dimens
What you're doing is safe because you're controlling the unexposed map
. You should probably make it private though and not protected, otherwise extending classes could incorrectly manipulate it. You can get rid of the compiler warning by casting into a runtime check, like this:
this.map = BaseCell[][].class.cast(Array.newInstance(BaseCell.class,
new int[] { width, height }));
Then if at some later point the code is potentially changed in an incompatible way that the compiler warning would mask out, it'll at least break early with a runtime exception at the construction of your map
. Keep in mind of course that Generics are simply erased at compile time.
Try guava's ObjectArrays.newArray(T[] reference, int length).
The problem with this Foo[][]
is that it in fact is defined as a Outer<T>.Foo[][]
, but the VM can't control (with ArrayStoreException
s) that you don't put Outer<S>.Foo
objects in it - this is why you get the warning. (This is why generic arrays are generally not considered typesafe.)
If you make sure this is not the case, then you have no problem.
I think the best choice in this situation is to simply use Object[]
.
Prior to generics, array types X[]
where X!=Object
are important types in APIs. We couldn't use List
which couldn't specify the component type. X[]
was the most useful one. Now with generics, we better use List<X>
instead of X[]
in APIs. (JDK still use X[]
in its APIs, even newer APIs, probably because they want to avoid dependencies among their packages)
That's for API. Within implementation details, we still need arrays, they are indispensible. However, Object[]
is enough. Actually if Java keeps only Object[]
and rid all other reference array types, nothing seriously bad would happen. All we need is arrays of objects to write our programs.
Of course, it would be silly to restraint ourselves from using X[]
when it's available and easy to use.
It would be equally silly, when X
is not a simple class, and X[]
is hard to work with, to waste our time to make it work. Nothing good is really achieved. In such situations, just use Object[]
and we'll save ourselves a lot of troubles.
So conclusion: externally, don't accept arrays, and don't give out arrays; internally, use X[]
if there's no sweat, otherewise use Object[]
and be happy.
This will allow it to work (along with an unchecked cast, which is normal for this situation since you want to have a variable that is the array of a generic type). The solution is realizing that just Foo
refers to the parameterized class Outer<T>.Foo
, since you are inside the scope of Outer<T>
; and that to get the actual raw class, you need to explicitly qualify it as Outer.Foo
:
foo = (Foo[][])new Outer.Foo[width][height];