Почему мы можем использовать массив с общей ссылкой

Отвечая на вопрос об этом здесь: https://stackoverflow.com/a/9872630/82609

Я попытался сделать следующее:

Comparator[] comparators = new Comparator[] {...};

Работает! Но в следующем нет:

Comparator[] comparators = new Comparator[] {...};

По связанному с этим вопросу я сделал предположение:

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

Если вы создадите массив типа X, вы НИКОГДА НИКОГДА не сможете поместить что-нибудь в нем, что НЕ ЯВЛЯЕТСЯ X. Если вы попытаетесь, вы получите ArrayStoreException

. Таким образом, разрешение создания массивов с дженериками приведет к другому например:

Если вы создадите массив типа X, вы НИКОГДА НИКОГДА не сможете поставить что-нибудь, что НЕ ЯВЛЯЕТСЯ X. Если вы попробуете, вы получите ArrayStoreException. Но вы МОЖЕТЕ добавить оба объекта Xи Xиз-за стирания типов!


Но, если подумать, не будет ли проблемой иметь:

Comparator[] comparators = new Comparator[] {...};

Я действительно не понимаю, почему это невозможно, поскольку использование такой вещи будет:

  • Проверять классы, вставленные во время выполнения
  • Проверка типа классов, вставленного во время компиляции

Наконец-то мы можем использовать массив со ссылкой на общий тип, и из-за невозможности создать массив с общим типом, я думаю, многие люди даже не знают, что это возможно.

Мне просто интересно, знает ли кто-нибудь причину этого выбора?

Это немного похоже на принуждение людей использовать List = new ArrayList();вместо использования List = new ArrayList();


dimitrisli вы привели хороший пример из знаменитой книги Джошуа Блоха.Как вы объяснили, опасно использовать оба общих массива + ковариацию и может привести к ClassCastException, в то время как мы ожидаем ArrayStoreException от массива с использованием ковариации.

Но обратите внимание, что следующее по-прежнему допустимо и ведет к тому же:

List[] stringLists = new List[1];
List intList = Arrays.asList(42);
Object[] objects = stringLists;
objects[0] = intList;
String s = stringLists[0].get(0);

Однако во время компиляции он выдает предупреждение о непроверенном приведении и, как вы упомянули, ClassCastException во время выполнения.

6
задан Community 23 May 2017 в 10:08
поделиться