Ниже я суммирую некоторые распространенные ловушки, такие как коллекции, дженерики и массивы для коллекций, После внимательного прочтения я уверен, что вы обязательно что-то выиграете.
1. Список, есть ли разница между списком> и списком?
Честно говоря, я уверен, что многие люди не знают разницы между List, List> и List
1. Давайте сначала посмотрим на список и список
Многие люди могут подумать, что использование List
List<Object> list;
и
List list;
Эти два определения совершенно одинаковы, но они не одинаковы. Посмотрите на следующий фрагмент кода
List<Integer> t1 = new ArrayList<>();
// 编译通过
List t2 = t1;
//编译失败
List<Object> t3 = t1;
t1 может быть назначен t2, но t1 не может быть назначен t3, будет выдано следующее исключение
Отсюда видно
List list;
и
List<Object> list;
Есть разница: переменная List может принимать любую общую переменную, а List — нет.
2. Смотрим, на что Лис> должен обратить внимание:
Посмотрите на следующий фрагмент кода:
List<Object> t1 = new ArrayList<>();
List<?> t2 = t1;
// 编译通过
t2.remove(0);
t2.clear();
// 编译不通过
t2.add(new Object());
List> — это общий тип, который может принимать присваивания из любой коллекции до того, как он будет назначен. Я думаю, что все это знают, но обратите внимание, чтоПосле присваивания в него нельзя добавлять элементы., выдает следующую ошибку:
Таким образом, List> обычно используется в качестве параметра для приема внешней коллекции или для возврата коллекции, которая не знает конкретных элементов.
Знаете тонкую разницу между List и List>, List
2. Вы действительно понимаете и ?
Мы знаем, что обобщенный список List
Для того, чтобы можно было разместить несколько типов, есть и , сначала поговорим о васвозможныйИзвестные знания:
1,для a, переменная может принимать множество T и его подклассов, верхней границей является T, а тип, взятый из a, будет приведен к T. Сосредоточьтесь на следующем примере:
Примечание. Сначала мы соглашаемся с тем, что Cat (кошка) наследуется от Animal (животное), а RedCat (черная кошка) наследуется от Cat.
List<Animal> animals = new ArrayList<>();
List<Cat> cats = new ArrayList<>();
List<RedCat> redCats = new ArrayList<>();
// 可以通过编译
List<? extends Cat> extendsCat = redCats;
// 不能通过编译,因为只能接受 Cat 及其子类的集合
extendsCat = animals;
// 重点注意:下面三行都不能通过编译
extendsCat.add(new Animal());
extendsCat.add(new Cat());
extendsCat.add(new RedCat());
// 重点注意:可以通过编译
extendsCat.add(null);
Обратите внимание, что самое важное в заключается в том, чтоНевозможно добавить внутрь все остальные элементы, кроме NULL, который похож на List> .
2. Теперь поговорим о , который немного противоположен .Для a, переменная может принимать набор T и его родительский класс, нижняя граница — T, а тип, взятый из a, будет приведен к Object. Сосредоточьтесь на следующем примере:
List<Animal> animals = new ArrayList<>();
List<Cat> cats = new ArrayList<>();
List<RedCat> redCats = new ArrayList<>();
// 可以通过编译
List<? super Cat> superCat = animals;
// 不能通过编译,因为只能接受 Cat 及其父类的集合
superCat = redCats;
// 重点注意:不能通过编译,只能添加 Cat 及其 Cat 的子类
superCat.add(new Animal());
// 重点注意,可以通过编译
superCat.add(new Cat());
superCat.add(new RedCat());
superCat.add(null);
Обратите внимание, Самое важное, что следует отметить в отношении super T>, это то, что вХотя значение T и его родительский класс могут быть приняты, внутрь добавляется только подкласс T и его T..
Суммировать
1. List extends T> a , можно присвоить a и его подклассы к a, и элементы, взятые из a, будут приведены к типу T, но следует учесть, что,не может добавить какой-либо элемент, кроме null, в.
2. Lista , можно присвоить a и его родительский класс a, а элементы, взятые из a, будут преобразованы в тип Object, но следует отметить, что можно добавлять элементы в a,Но можно добавить только T и элементы его подкласса..
3, дженерики и перезагрузка
Давайте сначала рассмотрим вопрос. Как вы думаете, можно ли ответить на следующий вопрос?компилироватьПроходят?
public class GernerTypes {
public static void method(List<Integer> list) {
System.out.println("List<Integer> list");
}
public static void method(List<String> list) {
System.out.println("List<String> list");
}
}
ответОшибка компиляции.
Параметры двух методов разные, почему он перегружен?
Фактически, в дженериках Java дженерики существуют только в исходном коде, а в скомпилированном байт-коде дженерики заменены народной тип, и вставьте код принуждения в соответствующее место. Для простоты понимания см. следующий пример кода:
// 源码
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
System.out.println(list.get(0));
}
После компиляции универсальный тип не существует, а код приведения вставляется в соответствующее место.После компиляции код, который мы декомпилируем, выглядит следующим образом:
// 反编译之后的代码
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
System.out.println((Integer)list.get(0));
}
После такой компиляции обобщенного типа не существует, а в соответствующее место вставляется механизм принудительного кода, который также называетсястереть.
Таким образом, два вышеуказанных метода имеют разные параметры, но после компиляции и стирания их параметры совпадают, поэтому компиляция завершается неудачно.
4. На что обратить внимание при преобразовании между массивами и наборами
1. Массив в коллекцию
Сначала рассмотрим пример.
public static void main(String[] args) {
String[] arr = {"one", "two", "three"};
// 数组转换成集合
List<String> list = Arrays.asList(arr);
// 向集合添加元素:编译正常,但运行时抛出了异常
list.add("four");
}
Добавление элемента в коллекцию вызывает следующее исключение:
Вопрос в том, зачем добавлять элемент в коллекцию выкинутого? ?
Давайте посмотрим, что на самом деле возвращает метод Arrays.asList(arr)?
Исходный код выглядит следующим образом:
Возвращаемый, очевидно, ArrayList, почему вы не можете добавлять элементы? ?
На самом деле этот ArrayList не является другим ArrayList, этот возвращенный ArrayList на самом деле является одним из массивов.внутренний класс. Внутренний класс также очень прост, не сравним с настоящим ArrayList, а часть исходного кода выглядит следующим образом:
И этот поддельный ArrayList напрямуюЦитироватьДа, в противном случае вы посмотрите на его конструктор (вторая нарисованная линия)
То есть ArrayList напрямую ссылается на массив arr, и если вы измените массив arr, он одновременно будет изменен на коллекцию списков.
Следующий код доказывает это
public static void main(String[] args) {
String[] arr = {"one", "two", "three"};
// 数组转换成集合
List<String> list = Arrays.asList(arr);
// 修改 arr
arr[0] = "0";
//打印看看
System.out.println(list.get(0));
}
Результат печати "0".
Следовательно, мы должны отказаться добавлять элементы в список, потому что длина массива arr равна 3, а элементов уже 3. Вы добавляете в него четвертый элемент, что точно недопустимо.
Поэтому особое внимание следует уделить процессу преобразования массива в коллекцию.
Рекомендуется преобразовать этот способ, чтобы быть более безопасным
List<String> list = new ArrayList<>(Arrays.asList(arr));
2. Установить в массив
Преобразование коллекции в массив относительно просто, поэтому я не буду тянуть много исходного кода для анализа, а лишь кратко упомяну несколько моментов, требующих внимания. Например, для следующего преобразования:
// 集合大小为 size
List<String> list = new ArrayList<>();
// 长度为 n 的数组
String[] arr = new String[n];
// 进行转换
list.toArray(arr);
1. Если длина массива меньше длины коллекции: Так как длины arr недостаточно, то элементы коллекции не будут присвоены arr, а будет создан новый массив и реверсирован.
2. Если длина массива не меньше набора: На данный момент длины arr достаточно, поэтому элементы набора напрямую копируются в массив arr, а новый элемент пересоздаваться не будет.
Список исходный код:
public <T> T[] toArray(T[] a) {
if (a.length < size)
// 重新创建一个数组来返回去
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
// 长度够的话直接复制给 a
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
Они попадают в ловушку, которую я считаю, что многие люди не знают, я помещаю ее в резюме, разбираясь, надеюсь, вы сможете что-то получить после прочтения.
Ниже я суммирую некоторые распространенные ловушки, такие как коллекции, дженерики и массивы для коллекций, После внимательного прочтения я уверен, что вы обязательно что-то выиграете.
Если вы считаете, что этот контент очень вдохновляет вас, вы можете
1,как, чтобы больше людей могли увидеть этот контент.
2,Подписывайтесь на меняДавайте станем долгосрочными отношениями
3. Подпишитесь на официальный аккаунт »трудолюбивый кодер», в нем более 100 оригинальных статей, а также я поделился большим количеством видео, книжных ресурсов и средств разработки, приветствую ваше внимание и читайте мои статьи как можно скорее.