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?

+3


source to share


3 answers


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);

      

+5


source


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 a T[]

    .
  • 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);
}

      

+2


source


javadoc Array#newInstance(..)

claims

If componentType

represents an array class, the number of dimensions of the new array is equal to the sum dimensions.length

and the number of dimensions componentType

. In this case, the component Type of the new array is the type of the component componentType

.

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 .

+1


source







All Articles