Pregunta java: creación de matriz genérica multidimensional


¿Cómo puedo hacer una matriz multidimensional de elementos genéricos en Java?

Considera la clase:

class A<T>
  {
    T t;
    public A(T t) { this.t = t; }
  }

Cuando intento crear una matriz multidimensional:

A<String>[][] array = new A<String>[2][3];

Obtuve el siguiente error:

generic array creation
A<String>[][] array = new A<String>[2][3];
                      ^

Intenté lo siguiente:

A<String>[][] array = (A<String>[][]) (new Object[2]3]);

Pero eso solo arroja: java.lang.ClassCastException

¿Cuál es la solución?

(Anticipo que la gente recomiende usar listas. Explique cómo lograr esto usando matrices).


7
2018-03-26 21:32


origen


Respuestas:


Pude hacer algo como esto

    @SuppressWarnings("unchecked") 
    A<String>[][] array = (A<String>[][]) Array.newInstance(new A<String>("dummy").getClass(), 2, 3);

EDITAR:

de la sugerencia de @dsg, lo siguiente omite la creación de un objeto temporal.

    @SuppressWarnings("unchecked") 
    A<String>[][] array = (A<String>[][]) Array.newInstance(A.class, 2, 3);

o (de la sugerencia de @ irreputable)

 @SuppressWarnings("unchecked")
 A<String>[][] array = new A[2][3];

4
2018-03-26 21:44



No puede crear una matriz de genéricos específicos de tipo de manera simple.

List<String>[] list = new List<String>[2]; //Illegal
List<?> aa[] = new List<?>[2]; // OK
...
A<?>[][] array = new A<?>[2][3]; // OK
A[0][0] = new A<String>(...);

Este es un artículo interesante sobre los genéricos Java 1.5, "Teoría y práctica Java: errores genéricos"


2
2018-03-26 22:06



Gracias a los comentarios, pude juntar una solución.

Como vimos, A<String>[][] array = new A<String>[2][3]; No funciona.

Aquí cómo construir un 2x3 gama de A<String> objetos que sí funcionan:

// get the class of the basic object
Class c = new A<String>("t").getClass();

// get the class of the inner array
A<String>[] a0 = (A<String>[]) java.lang.reflect.Array.newInstance(c, 0);

// construct the outer array
A<String>[][] array = (A<String>[][]) java.lang.reflect.Array.newInstance(a0.getClass(), 2); 

// fill it with instances of the inner array
for (int i = 0; i < 2; ++ i)
{   
  array[i] = (A<String>[]) java.lang.reflect.Array.newInstance(c, 3); 
}

Una versión mucho más limpia (Gracias, @Balla R):

@SuppressWarnings("unchecked")
A<String>[][] array = (A<String>[][]) java.lang.reflect.Array.newInstance(A.class,2,3);

1
2018-03-26 21:57



new A[][] y echarlo a A<String>[][]


1
2018-03-26 22:17



¿Por qué no haces algo como esto? (No genérico)

String[][] non_generic_array = new String[][];

Y crea una clase de utilidad para implementar las funciones que hiciste A<T> (como supongo que hay). P.ej:

Cuando tenías esto en A:

public class A<T>
{
    T obj;
    public A(T obj) { this.obj = obj; }

    public void someFunction() { ... }
}

Puedes hacer una clase de utilidad:

public class AUtils
{

    public static <T> void someFunction(T obj)
    {
        // Here your code, applied to obj
    }

}

1
2018-03-26 22:11



Hmm, pensé que Java Arrays (a partir de Java 6) no era compatible con los genéricos. Uno de mis mayores "wtf" cuando comencé a programar con genéricos en Java.


0
2018-03-26 22:07



class A<T> 
{
    T s;

    public A(T t)
    {
        s = t;
    }

    public String getType()
    {
        return s.getClass().toString();
    }

    public T getThing()
    {
        return s;
    }
}

public static void main(String[] args) 
{
    A<?>[][] a = new A<?>[2][3];
    a[0][1] = new A<String>("hi");

    System.out.println(a[0][1].getType());
    System.out.println(a[0][1].getThing());

    A<String> b = (A<String>) a[0][1];
}

salida:

clase java.lang.String

Hola


0
2018-03-26 22:17