Какова причина, я не могу создать универсальные типы массива в Java?

Что является причиной, почему Java не позволяет нам делать

private T[] elements = new T[initialCapacity];

Я мог понять, что.NET не позволила нам делать это, как в.NET у Вас есть типы значения, которые во времени выполнения могут иметь различные размеры, но в Java все виды T будут ссылками на объект, таким образом имея тот же размер (исправьте меня, если я неправ).

Какова причина?

259
задан Hearen 12 March 2019 в 00:19
поделиться

6 ответов

Это потому, что массивы Java (в отличие от дженериков) содержат во время выполнения информацию о типе своего компонента. Таким образом, вы должны знать тип компонента при создании массива. Поскольку вы не знаете, что такое T во время выполнения, вы не можете создать массив.

193
ответ дан 23 November 2019 в 02:39
поделиться

Причина, по которой это невозможно, заключается в том, что Java реализует свои Generics исключительно на уровне компилятора, и для каждого класса создается только один файл класса. Это называется Type Erasure.

Во время выполнения скомпилированный класс должен обрабатывать все свои использования с помощью одного и того же байткода. Так, new T[capacity] будет совершенно не знать, какой тип нужно инстанцировать.

31
ответ дан 23 November 2019 в 02:39
поделиться

Мне нравится косвенный ответ Автор Gafter . Однако я считаю, что это неправильно. Я немного изменил код Гафтера. Он компилируется и какое-то время работает, а затем взрывается там, где предсказал Гафтер.

class Box<T> {

    final T x;

    Box(T x) {
        this.x = x;
    }
}

class Loophole {

    public static <T> T[] array(final T... values) {
        return (values);
    }

    public static void main(String[] args) {

        Box<String> a = new Box("Hello");
        Box<String> b = new Box("World");
        Box<String> c = new Box("!!!!!!!!!!!");
        Box<String>[] bsa = array(a, b, c);
        System.out.println("I created an array of generics.");

        Object[] oa = bsa;
        oa[0] = new Box<Integer>(3);
        System.out.println("error not caught by array store check");

        try {
            String s = bsa[0].x;
        } catch (ClassCastException cause) {
            System.out.println("BOOM!");
            cause.printStackTrace();
        }
    }
}

Результат -

I created an array of generics.
error not caught by array store check
BOOM!
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at Loophole.main(Box.java:26)

Так что мне кажется, что вы можете создавать универсальные типы массивов в java. Я неправильно понял вопрос?

4
ответ дан 23 November 2019 в 02:39
поделиться

Цитата:

Массивы универсальных типов не разрешены, потому что они не звучат. В проблема связана с взаимодействием Массивы Java, которые не статически звук, но проверяется динамически, с дженериками, которые статически звук и не проверяется динамически. Вот как можно использовать лазейка:

 class Box  {
конечный T x;
Box (T x) {
this.x = x;
 }
}
class Loophole {
public static void main (String [] args) {
Поле  [] bsa = новое поле  [3];
Объект [] oa = bsa;
oa [0] = новое поле <Целое число> (3); // ошибка не обнаружена проверкой хранилища массива
Строка s = bsa [0] .x; // БУМ!
 }
}

Мы предложили решить эту проблему проблема с использованием статически безопасных массивов (aka Variance), но, который был отклонен для Тигра.

- gafter

(я полагаю, что это Нил Гафтер , но не уверен)

См. Контекст здесь: http: //forums.sun .com / thread.jspa? threadID = 457033 & forumID = 316

134
ответ дан 23 November 2019 в 02:39
поделиться

Не предоставив достойного решения, вы просто получите что-то хуже, ИМХО.

Обычно это решается следующим образом.

T[] ts = new T[n];

заменяется на (при условии, что T расширяет Object, а не другой класс)

T[] ts = (T[]) new Object[n];

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

Большинство примеров того, почему нельзя просто использовать Object[], в равной степени относятся к List или Collection (которые поддерживаются), поэтому я считаю их очень слабыми аргументами.

Примечание: это одна из причин, по которой сама библиотека Collections не компилируется без предупреждений. Если этот сценарий использования не может быть поддержан без предупреждений, то в модели generics что-то фундаментально нарушено IMHO.

44
ответ дан 23 November 2019 в 02:39
поделиться

Основная причина заключается в том, что массивы в Java являются ковариантными.

Есть хороший обзор здесь.

5
ответ дан 23 November 2019 в 02:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: