#java #arrays #list #arraylist #collections
#java #массивы #Список #arraylist #Коллекции
Вопрос:
//Splitting a string and passing it to a String Array
String[] b1 = a1.split("");
//The Following throws a compile-time error
ArrayList<String> arrayList1 = new ArrayList<String>();
arrayList1 = Arrays.asList(b1);
//The following works
List<String> arrayList1 = new ArrayList<String>();
arrayList1 = Arrays.asList(b1);
Я хочу знать, почему первый подход выдает ошибку, тогда как второй работает хорошо? ArrayList
реализует List
интерфейс, поэтому он должен хорошо работать.
Комментарии:
1. Все немецкие овчарки — собаки, но не каждая собака является немецкой овчаркой. Здесь:
ArrayList
«is-a»List
. Таким образом, вы можете назначитьArrayList
дляList
. НоList
также может быть другого типа (runtime), поэтому вы не можете назначитьList
более конкретныйArrayList
.2. Обратите внимание, что список, возвращаемый
Arrays.asList
неjava.util.ArrayList
. Это совершенно другой класс, который также названArrayList
, помещенный внутриjava.util.Arrays.ArrayList
3. Вы должны понимать ссылки . Ваши переменные имеют тип ссылки , и назначение новой ссылки перезаписывает старую. Перезапись ссылки не имеет ничего общего с объектом. Другими словами, инициализация
arrayList1 = new ArrayList<String>()
совершенно бессмысленна, когда вы перезаписываете ссылку прямо в следующем операторе другой ссылкой. Присвоение допустимо, когда тип переменной совместим со ссылкой. Старая ссылка и объект, на который она указывает, совершенно не имеют значения.
Ответ №1:
ArrayList
реализуетList
интерфейс, поэтому он должен хорошо работать.
Нет, это не так, как это работает. Если что-то возвращает реализацию интерфейса, вы можете назначить его объекту, объявленному как этот интерфейс, а не наоборот.
Это то, что вы делаете, когда вы делаете
List<String> arrayList1 = new ArrayList<String>();
Что абсолютно законно.
Но что, если asList
возвращает что-то, что является списком, но не ArrayList (что здесь и происходит)? Вы получаете сообщение об ошибке, потому что вы присваиваете что-то, что не является ArrayList
(и не происходит от него) ArrayList
.
Также обратите внимание, что, как только вы это сделаете arrayList1 = Arrays.asList(b1);
во втором тесте, тот факт, что вы назначили new ArrayList
для arrayList1
, совершенно не имеет значения, поскольку вы перезаписываете его в следующей строке, так что arrayList1
это просто a List
, как объявлено.
Ответ №2:
Java статически типизирована, когда вы говорите, что переменная является a, String
тогда вы не можете назначить int
ей . То же самое относится и к вашему примеру. Когда вы объявляете arrayList1
как a ArrayList<String>
, вы не можете назначить List<String>
ему . Потому что вы не можете быть уверены, что значение, возвращаемое из Arrays.asList()
, действительно является экземпляром java.util.ArrayList
.
Также будьте осторожны, существует два класса Java с именем ArrayList
. Тот, от java.util
и тот, от java.util.Arrays
. Первый является public
, а второй находится private
внутри Arrays
класса
Ответ №3:
Arrays.asList(b1) возвращает объект типа java.util.Массивы.ArrayList, который является вложенным классом в массивах.
Другими словами, ваш вопрос заключается в том, почему b1 типа java.util.Массивы.ArrayList не может быть приведен к arrayList1, который имеет тип java.util.ArrayList : это два совершенно разных типа, которые вообще не связаны.
Если вам нужен java.util.Вы можете просто создать копию:
ArrayList arrayList1 = новый ArrayList<>(Arrays.asList(b1));
С уважением