Отвечая на вопрос об этом здесь: https://stackoverflow.com/a/9872630/82609
Я попытался сделать следующее:
Comparator<String>[] comparators = new Comparator[] {...};
Оно работает! Но следующее не делает:
Comparator<String>[] comparators = new Comparator<String>[] {...};
По соответствующему вопросу я сделал предположение:
Я предполагаю, что изначально контракт массива может быть примерно таким:
Если вы создадите массив типа X, вы НИКОГДА не сможете поместить в него что-либо, что НЕ ЯВЛЯЕТСЯ X. Если вы попытаетесь, вы получите исключение ArrayStoreException.
Таким образом, разрешение массивов с созданием дженериков приведет к другому правилу, например:
Если вы создадите массив типа
X<Y>
, вы НИКОГДА не сможете поместить что-либо, что НЕ ЯВЛЯЕТСЯ X. Если вы попытаетесь, вы получите исключение ArrayStoreException. Но вы МОЖЕТЕ добавить объектыX<Y>
иX<Z>
из-за стирания типов!
Но, если подумать, не будет ли проблемой иметь:
Comparator<String>[] comparators = new Comparator<String>[] {...};
Я действительно не понимаю, почему это невозможно, поскольку использование такой вещи:
- Проверьте классы, вставленные во время выполнения
- Проверьте тип классов, вставленный во время компиляции
Наконец, мы можем использовать массив со ссылкой на общий тип, и из-за невозможности создать массив с общим типом, я думаю, многие люди даже не знают, что это возможно.
Мне просто интересно, знает ли кто-нибудь причину этого выбора?
Это как заставить людей использовать List<String> = new ArrayList();
вместо List<String> = new ArrayList<String>();
.
dimitrisli, вы привели хороший пример из знаменитой книги Джошуа Блоха. Как вы объяснили, опасно использовать оба общих массива + ковариацию и может привести к ClassCastException, в то время как мы ожидаем ArrayStoreException от массива с использованием ковариации.
Но обратите внимание, что следующее все еще является законным и приводит к тому же:
List<String>[] stringLists = new List[1];
List<Integer> intList = Arrays.asList(42);
Object[] objects = stringLists;
objects[0] = intList;
String s = stringLists[0].get(0);
Однако он выдает предупреждение о непроверенном приведении во время компиляции и, как вы упомянули, ClassCastException во время выполнения.