Casting Arrays.asList вызывает исключение: java.util.Arrays $ArrayList нельзя отбрасывать в java.util.ArrayList
Я новичок в Java и пытаюсь понять, почему первый фрагмент кода не вызывает это исключение, а второй. Поскольку массив строк передается в Arrays.asList в обоих случаях, не должны ли оба фрагмента создавать исключение или не создавать исключение?
Exception in thread "main" java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList
Первый фрагмент (не вызывает исключения):
ArrayList<ArrayList<String>> stuff = new ArrayList<ArrayList<String>>();
String line = "a,b,cdef,g";
String delim = ",";
String[] pieces = line.split(delim);
stuff.add((ArrayList<String>) Arrays.asList(pieces));
Второй фрагмент (вызывает исключение):
ArrayList<ArrayList<String>> stuff = new ArrayList<ArrayList<String>>();
String[] titles = {"ticker", "grade", "score"};
stuff.add((ArrayList<String>) Arrays.asList(titles));
Если это уместно, я использую JavaSE 1.6 в Eclipse Helios.
Ответы
Ответ 1
Для меня (с использованием Java 1.6.0_26) первый фрагмент дает то же исключение, что и второе. Причина в том, что метод Arrays.asList(..)
возвращает только List
, не обязательно ArrayList
. Поскольку вы действительно не знаете, какой тип (или реализация) List
возвращает этот метод, ваш приведение в ArrayList<String>
небезопасно. В результате он может работать или не работать должным образом. С точки зрения стиля кодирования хорошим решением для этого было бы изменить ваше объявление stuff
на:
List<List<String>> stuff = new ArrayList<List<String>>();
который позволит добавить все, что выходит из метода Arrays.asList(..)
.
Ответ 2
Если вы сделаете это, вы не получите никакого CCE:
ArrayList<ArrayList<String>> stuff = new ArrayList<ArrayList<String>>();
String[] titles = {"ticker", "grade", "score"};
stuff.add(new ArrayList<String>(Arrays.asList(titles)));
Как ясно сказано в сообщении, класс java.util.ArrayList
не совпадает с вложенным статическим классом java.util.Arrays.ArrayList
. Отсюда исключение. Мы преодолеем это, обернув возвращаемый список, используя java.util.ArrayList
.
Ответ 3
Проблема заключается в том, что вы указали свой список, содержащий ArrayLists
, и подразумевая никаких других реализаций списков. Arrays.asList()
возвращает свою собственную реализацию списка, основанного на реализации параметра массива, который не может быть ArrayList. Это ваша проблема.
В более широком смысле вы сталкиваетесь с проблемой классического стиля кода: вы должны ссылаться на абстрактные интерфейсы (т.е. List
), а не на конкретные реализации (т.е. ArrayList
). Вот как выглядит ваш код:
List<List<String>> stuff = new ArrayList<List<String>>();
String[] titles = { "ticker", "grade", "score" };
stuff.add((List<String>) Arrays.asList(titles));
Я тестировал этот код, и он работает без ошибок.
Ответ 4
Не нужно бросать вручную. Этот простой код может помочь вам,
List stuff = new ArrayList();
String line = "a,b,cdef,g";
String delim = ",";
stuff.addAll(Arrays.asList(line.split(delim)));
Ответ 5
Используя отладчик, я определил, что Array.asList(titles) возвращает "ArrayLay ArrayList" (т.е. внутренний класс класса Arrays), а не java.util.ArrayList.
Всегда лучше использовать интерфейс в левой части выражений, в данном случае List, а не конкретный ArrayList. Это отлично работает:
List<List<String>> stuff = new ArrayList<List<String>>();
String[] titles = {"ticker", "grade", "score"};
stuff.add((List<String>) Arrays.asList(titles));
Ответ 6
Если вы хотите использовать свое свойство как ArrayList < 'T' > , вам нужно только объявить его и создать getter.
private static ArrayList<String> bandsArrayList;
public ArrayList<String> getBandsArrayList() {
if (bandsArrayList == null) {
bandsArrayList = new ArrayList<>();
String[] bands = {"Metallica", "Iron Maiden", "Nirvana"};
bandsArrayList.addAll(Arrays.asList(bands));
}
return bandsArrayList;
}
Инициализирует переменную и использует метод [addAll (Collection collection)] (http://developer.android.com/intl/pt-br/reference/java/util/ArrayList.html#addAll(java.util.Collection))
Ответ 7
Во-первых, Arrays.asList() никогда не следует бросать в ArrayList. Во-вторых, поскольку generics были введены в java-язык программирования, литье все еще актуально при использовании устаревших API-интерфейсов до генериков.
В-третьих, никогда использовать конкретные классы слева от оператора присваивания.
Нижняя строка, скажем
List<List<String>> stuff = new ArrayList<List<String>>();
String line = "a,b,cdef,g";
String delim = ",";
String[] pieces = line.split(delim);
stuff.add(Arrays.asList(pieces));
List<List<String>> stuff = new ArrayList<List<String>>();
String[] titles = {"ticker", "grade", "score"};
stuff.add(Arrays.asList(titles));
и будьте счастливы.