Как реализовать функцию для преобразования универсального типизированного массива в универсальный типизированный 2-мерный массив в Java?

#java #arrays #generics

#java #массивы #общие сведения

Вопрос:

 public static <T> T[][] toTwoDim(T[] array)
  

Сигнатура функции, как указано выше..
Это универсальная типизированная функция, которая может использоваться независимо от типа данных, содержащихся в массиве.
как правило, она получает массив и возвращает 2-мерный массив, половина элементов которого находится в первой строке, а другая половина — во второй строке.
Я понятия не имею, как это реализовать, потому что я не смог создать универсальный типизированный 2-мерный массив внутри функции.
Кто-нибудь мне поможет?
Спасибо!

Комментарии:

1. Я думаю, точная процедура не очень важна для того, чтобы заботиться о ней. Основная проблема, с которой я столкнулся, заключается в том, как я мог создать соответствующее возвращаемое значение, иначе говоря, универсальный типизированный двумерный массив. Мы можем предположить более простое отображение, как я описал в исходном сообщении: функция разбивает массив на две части, каждая часть имеет свои половинные элементы, и одна часть хранится в первой «строке» двумерного массива, а другая часть — во второй «строке».

Ответ №1:

Я довольно долго играл с этим, и, насколько я понимаю, по причинам удаления типа, это невозможно.

Основываясь на других примерах создания массивов параметров универсального типа, кажется, что должно сработать что-то вроде следующего кода, но в конечном итоге это приводит к сбою только при возврате функции, где Object[][] не может быть приведено к Integer[][] . Ранее это завершилось бы неудачей, за исключением того, что IIRC, из которого исходное приведение (T[][]) , в основном удаляется во время компиляции и предотвращает предупреждение, поэтому оно не оказывает реального влияния.

 @SuppressWarnings("unchecked")
public static <T> T[][] toTwoDim(T[] array){
    int halflen = array.length / 2;

    T[][] foo = (T[][]) new Object[2][];

    foo[0] = (T[]) new Object[halflen];
    foo[1] = (T[]) new Object[halflen];

    for(int i = 0; i < halflen; i  ){
        foo[0][i] = array[i];
        foo[1][i] = array[i halflen];
    }

    System.out.println(Arrays.asList(foo[0]));
    System.out.println(Arrays.asList(foo[1]));

    return foo;
}

public static void main(String[] a){
    Integer[] bar = {1,2,3,4};
    Integer[][] foo = toTwoDim(bar);
    System.out.println(Arrays.asList(foo[0]));
}
  

Комментарии:

1. спасибо за ваше объяснение, может быть, я бы нашел другой подход к выполнению задачи.

Ответ №2:

Это должно быть возможно сделать.

Основной подход заключается в использовании java.lang.reflect.Array.newInstance(clazz, dimX, dimY) для создания экземпляра массива.

  • Если вы хотите, чтобы базовый тип результирующего массива совпадал с базовым типом аргумента, то используйте отражение, чтобы получить базовый тип из array.getClass() .

  • Если вы хотите, чтобы базовый тип результирующего массива был <T> , то вам нужно будет добавить дополнительный аргумент к, toTwoDim тип которого Class<T> , и использовать его для передачи объекта класса для требуемого базового типа массива. (Удаление типа означает, что toTwoDim метод не может определить объект класса для <T> во время выполнения. Передача объекта класса в качестве аргумента является стандартным обходным путем.)

Ответ №3:

Я нашел идеальное решение:

 @SuppressWarnings("unchecked")
public static <T> T[][] toTwoDim(T[] array) {
    Class<T> ctype = (Class<T>) array.getClass().getComponentType();
    int halfLength = array.length / 2;
    T[][] ret = (T[][]) Array.newInstance(ctype, 2, 1);
    T[] r1 = (T[]) Array.newInstance(ctype, halfLength);
    T[] r2 = (T[]) Array.newInstance(ctype, array.length - halfLength);
    ret[0] = r1;
    ret[1] = r2;
    for (int i = 0; i < halfLength; i  )
        r1[i] = array[i];
    for (int i = 0; i < array.length - halfLength; i  ) {
        r2[i] = array[i   halfLength];
    }
    return ret;
}

public static void main(String[] a) {
    Integer[] bar = { 1, 2, 3, 4, 5 };
    Integer[][] dims = toTwoDim(bar);
    for (Integer[] r : dims) {
        for (Integer d : r) {
            System.out.print(d   " ");
        }
        System.out.println();
    }
}
  

вывод:
1 2
3 4 5

общий тип функции ‘toTwoDim’ удален, но тип элемента входящего массива может быть получен с помощью отражения!

Ответ №4:

Вы могли бы сделать это, что не требует подавления каких-либо предупреждений.

 public static <T> T[][] toTwoDim(Class<T[][]> clazz, T[] array)  
{  
   int halfLength = array.length / 2;  
   T[][] ret = clazz.cast(Array.newInstance(clazz.getComponentType().getComponentType(), 2, halfLength   1));  
   System.arraycopy(array, 0, ret[0], 0, halfLength);  
   System.arraycopy(array, halfLength, ret[1], 0, array.length - halfLength);  
   return ret;  
}