java: создание многомерного универсального массива

как сделать многомерный массив общих элементов в java?

рассмотрим класс:

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

когда я пытаюсь создать многомерный массив:

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

я получаю следующую ошибку:

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

я попробовал следующий:

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

но это просто броски: java.lang.ClassCastException

что исправить?

(Я ожидаю, что люди рекомендуют использовать списки. Пожалуйста, объясните, как достичь этого с помощью матрицы.)

7 ответов


я смог сделать что-то вроде этого

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

EDIT:

из предложения @dsg следующее пропускает создание временного объекта.

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

или (из предложения @irreputable)

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

вы не можете создать массив универсального типа простым способом.

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

Это интересная статья о Java 1.5 generics,"Java теория и практика: дженерики gotchas"


благодаря комментариям я смог собрать воедино решение.

как мы видели, A<String>[][] array = new A<String>[2][3]; не работает.

вот как построить 2x3 массив A<String> объекты, работает:

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

гораздо более чистая версия (Спасибо, @Balla R):

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

new A[][] и A<String>[][]


почему бы вам не сделать что-то вроде этого: (non-generic)

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

и сделать класс утилиты для реализации функций, которые вы сделали в A<T> (как я полагаю, есть). Например:

когда у вас было это в A:

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

    public void someFunction() { ... }
}

вы можете сделать служебный класс:

public class AUtils
{

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

}

Хм, я думал, что массивы Java (начиная с Java 6) не поддерживают обобщения. Один из моих самых больших "wtf", когда я начал программировать с дженериками на java.


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];
}

выход:

класс java.ленг.Строка

привет