Initializing a 2D Shared Array
I tried to create a 2 dimensional generic array in java. I get no compilation errors, but I get an exception when I run the code:
Exception in thread "main" java.lang.ClassCastException: Cannot cast [[[Ljava.lang.String; to [[Ljava.lang.String;
at java.lang.Class.cast(Unknown Source)
at Tabela.<init>(Tabela.java:8)
at TabelaTest.main(TabelaTest.java:4)
Here is the code:
import java.lang.reflect.Array;
public class Tabela<T> {
private T[][] data;
public Tabela(Class<T[][]> c,int sizeX, int sizeY) {
this.data = c.cast(Array.newInstance(c.getComponentType(), sizeX, sizeY));
}
public void setInfoAt(T info, int x, int y) {
this.data[x][y] = info;
}
public T getObjectAt(int x, int y) {
return this.data[x][y];
}
}
public class TabelaTest {
public static void main(String args[]) {
Tabela<String> tabela = new Tabela<String>(String[][].class, 2, 2);
tabela.setInfoAt("a", 0, 0);
tabela.setInfoAt("b", 0, 1);
tabela.setInfoAt("c", 1, 0);
tabela.setInfoAt("d", 1, 1);
System.out.println(tabela.getObjectAt(1, 0));
}
}
It looks like I cannot use this method for 2D arrays.
EDIT:
Using the method from unholysampler it works now. The constructor has been changed to:
public Tabela(Class<T> c,int sizeX, int sizeY) {
this.data = (T[][])Array.newInstance(c, sizeX, sizeY);
}
The point is that the eclipse continues to warn me about this actor (T [] []). I can suppress it, but is it okay to ignore it?
source to share
If you look at the error message, you can see that the number of square brackets is different.
Cannot cast [[[Ljava.lang.String; to [[Ljava.lang.String;
--- --
You get an extra level of the array due to the way you call Array.newInstance()
. If you want to create an array String
, you must use:
String[] arr = (String[])Array.newInstance(String.class, 5);
Notice that you are passing the base class type and the method "adds" the parenthesis layer. Your call says that you want an array containing 2D array instances String
. Instead, you want to just just go to the base class and then specify the dimensions.
Array.newInstance(String.class, sizeX, sizeY);
source to share
This error is in your constructor:
public Tabela(Class<T[][]> c,int sizeX, int sizeY) {
this.data = c.cast(Array.newInstance(c.getComponentType(), sizeX, sizeY));
}
-
c.getComponentType()
actually aT[]
. -
Array.newInstance(Class, int...)
returns an array with the same dimensions as the array. You are passing two values, the array is two dimensional.Array.newInstance( c.getComponentType(), // returns T[] sizeX, sizeY ) // returns T[][][]
What would be the runtime equivalent new T[sizeX][sizeY][]
if possible (type erasure).
I would do this:
public Tabela(Class<T> c,int sizeX, int sizeY) {
this.data = Array.newInstance(c, sizeX, sizeY);
}
source to share
javadoc Array#newInstance(..)
claims
If
componentType
represents an array class, the number of dimensions of the new array is equal to the sumdimensions.length
and the number of dimensionscomponentType
. In this case, the component Type of the new array is the type of the componentcomponentType
.
Since componentType
String[]
, the array class number becomes the sum of the measurements dimensions.length
, 2
and the number of measurements componentType
, 1
in total 3
.
Your challenge
Array.newInstance(c.getComponentType(), sizeX, sizeY)
becomes equivalent
new String[2][2][]
Instead, you can call the method newInstance(Class, int)
like
Array.newInstance(c.getComponentType(), sizeX)
to create
new String[2][]
but you will have to instantiate the nested arrays manually.
Or refactor your constructor parameters to implement the unholysampler solution .
source to share