Предположим, есть такой код:
List<Integer>[] lists = new ArrayList<Integer>[10];
Компилятор не пропустит такого объявления. Почему?
P.S. Я знаю, что создавать подобный массив в реальном коде не стоит (лучше использовать коллекции) и знаю способы как обойти эту ошибку.
В документации сказано, что создание массивов из объектов параметризованного типа запрещено для избежания подобной ситуации:
//Предположим, что такое объявление было бы возможно
List<String>[] lsa = new List<String>[10];
Object o = lsa;
Object[] oa = (Object[])o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
//присвоение не вызывает ошибок
oa[1] = li;
//Ошибка в run-time: ClassCastException.
String s = lsa[1].get(0);
В этой ситуации код бы скомпилировался, но "сломался" при запуске.
Однако допускается использование wildcard <?>
с явным приведением к String
в последней строке:
List<?>[] lsa = new List<?>[10];
Object o = lsa;
Object[] oa = (Object[])o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
//Корректно
oa[1] = li;
//Ошибка в run-time, но приведение было явным
String s = (String)lsa[1].get(0);
Раз приведение было явным, то это говорит о том, что, во-первых, здесь может возникнуть ClassCastException
, а во-вторых, что это уже забота программиста - приведение к корректному типу.
Да, в первой строке можно написать так:
List<String>[] lsa = new List[10];
И тогда код скомпилируется и "свалится" с ClassCastException
в последней строке. Однако тут нужно учитывать, что в этой записи в левой части используется параметризованный тип, а в правой - raw type. Такая запись не является рекомендуемой к использованию (кроме ситуаций, когда это действительно необходимо). В частности, потому что допускает некорректную ситуацию:
List<Integer> ints = Arrays.asList(1);
List<String>[] lsa = new List[] { ints };
String s = lsa[0].get(0);
Код скомпилируется и, как это было уже не раз в ответе, приведёт к ClassCastException
в последней строке.
Судя по документации
You cannot create arrays of parameterized types. For example, the following code does not compile:
List<Integer>[] arrayOfLists = new List<Integer>[2];
// compile-time error
Так что придется делать список списков.
Можно попробовать сделать так:
ArrayList<Integer>[] group = (ArrayList<Integer>[])new ArrayList[4];
Но, ИМХО, это костыльно.
Проблема в том, что массивы в Java ковариантны (т.е. если класс B
- наследник A
, то B[]
- наследник A[]
и мутабельны (значение элементов массива можно менять). Т.е. можно написать:
String[] strings = new String[1];
Object[] objects = strings; // ковариантность
objects[0] = new Object(); // мутабельность, эта строка компилируется,
// но при запуске выдаст исключение.
При попытке использовать элемент strings
, например strings[0].length()
, произошла бы ошибка, т.к. на самом деле в массиве лежит Object
. Такие ошибки сложно исправлять, потому что заполнение и использование массива могут находиться в разных частях программы. Поэтому, при присвоении значения элементу, происходит проверка соответствия типа, и может быть выброшено исключение java.lang.ArrayStoreException
.
Дженерики в java реализованы с помощью type erasure, информация о конкретных значениях параметров типов известна только на этапе компиляции (non-reifiable types), а во время выполнения типы List<String>
и List<Integer>
"стираются" до простого List
. Поэтому проверить, что элементу массива List<String>[]
присваивается именно List<String>
невозможно, и создание массивов с non-reifiable элементами запрещено.
Дженерики по-умолчанию инвариантны (List<String>
не является наследником List<Object>
и наоборот), поэтому можно использовать коллекции обобщенных типов.
Виртуальный выделенный сервер (VDS) становится отличным выбором
здравствуйте,есть код который нормально компилируется javase,когда хочу вызвать этот код в javaee в сервлете вылетает ошибка NullPointerException почему...
Задача такова: зашифрованную картинку, которая хранится как двумерный массив пикселей, нужно спрятать в пикселе текущей картинкиТаким образом,...
Здравствуйте, недавно начал изучать Android, вылезла такая ошибка: