Генерирование Java и инициализация массива
Какое объяснение для следующего:
public class GenericsTest {
//statement 1
public ArrayList<Integer>[] lists;
public GenericsTest()
{
//statement 2
lists = new ArrayList<Integer>[4];
}
}
Компилятор принимает оператор 1. Утверждение 2 помечено компилятором для "создания общего массива".
Хорошее объяснение, которое я видел относительно отказа от общих массивов, - этот, утверждая, что поскольку массивы являются ковариантными, а дженерики - это вы не можете подорвать типичная типизация, если вы разрешили общие массивы.
Оставляя в стороне аргумент о том, должен ли язык идти на крайние этапы создания такого сложного несогласованности в лечении дженериков, чтобы вы не стреляли в себя независимо от того, насколько сильно вы пытаетесь (и если кто-нибудь знает о хороших дискуссиях по относительным достоинствам/недостаткам проблемы, пожалуйста, напишите мне, мне было бы интересно увидеть аргументы), зачем нужно утверждать (1), если (2) нет?
Ответы
Ответ 1
Похоже, что есть неясные случаи, когда вы можете непреднамеренно вызвать ClassCastException, как описано здесь
http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf (раздел 7.3)
интересное обсуждение этой темы можно найти здесь
http://courses.csail.mit.edu/6.170/old-www/2006-Spring/forum/index.php%3Ftopic=324.msg1131.html
Ответ 2
Это потому, что вы не можете создать, но можете использовать их:
public class GenericsTest {
//statement 1
public ArrayList<Integer>[] lists;
public GenericsTest()
{
//statement 2
lists = new ArrayList[4];
//statement 3
lists[0].add(new Integer(0));
//statement 4
lists[0].add(new String(""));
}
}
Утверждение 3 возможно, оператор 4 приведет к ошибке компилятора.
Ответ 3
Итак, актуальный вопрос: почему нет ошибки для объявления общего массива?
Вы всегда будете получать ошибку в том месте, где вы делаете что-то ошибочное. Добавление ошибки, когда технически проблема не возникает, просто добавляет к беспорядку (хотя редактор может захотеть указать это на вас).
В некоторых случаях вам может понадобиться немного свести правила с помощью непроверенного броска. Нет необходимости принудительно заставлять код забивать больше предупреждающих подавлений, чем необходимо (кроме указания глупости).
Ответ 4
В этом случае я бы не стал использовать массивы именно по этой причине. Объявление "списков" в исходном коде может быть
List<List<Integer>> lists = new ArrayList<List<Integer>>(4);
for(int i = 0; i < 4; i++) lists.add(null); // or add an empty ArrayList<Integer>
(вы должны использовать интерфейс, а не реализацию в объявлениях переменных)
Вместо синтаксиса array [] вы должны использовать get() или set(). Кроме этого, это эквивалентно.