Below I summarized sets, generics, array rotation sets and other common traps, carefully read, I believe you will definitely gain.
List, List<? > is different from List<Object>?
To be honest, I’m sure a lot of people don’t know List, List<? > and List<Object>.
List<Object> = List<Object>
Many people might think that List<Object> is the same as List, for example
List<Object> list;
with
List list;
The two definitions are exactly the same, but they are different. Take a look at the code below
List<Integer> t1 = new ArrayList<>(); List t2 = t1; List<Object> t3 = t1;Copy the code
T1 can be assigned to T2, but t1 cannot be assigned to t3, raising the following exception
You can see it here
List list;
with
List<Object> list;
A List variable can accept any generic variable, whereas a List cannot.
2. We are looking at Lis<? > < p style = “max-width: 100%; clear: both; min-height: 1em;
Take a look at the following code:
List<Object> t1 = new ArrayList<>(); List<? > t2 = t1; // Compile through t2.remove(0); t2.clear(); T2.add (new Object());Copy the code
List
So the List <? > is usually used as an argument to accept an external collection, or to return a collection of unknown elements.
A List with the List <? >, List<Object> nuances, okay?
2, <? Extends T > and <? Super T> Do you really understand?
We know that the generic List<T> can only place one type. If you use List<Object> to place multiple types and then cast them, you lose the purpose of generics.
To be able to place multiple types, the
and
, here are some things you probably already know:
1. For
a. The a variable accepts a collection of T and its T subclasses with an upper bound of T, and any type fetched from A is cast to T. Focus on the following example:
Note: We agree that Cat comes from Animal, and RedCat comes from Cat
List<Animal> animals = new ArrayList<>(); List<Cat> cats = new ArrayList<>(); List<RedCat> redCats = new ArrayList<>(); // You can compile List<? extends Cat> extendsCat = redCats; // Cannot compile because only Cat and its subclasses can be accepted extendsCat = animals; Extendsat.add (new Animal()); extendsCat.add(new Cat()); extendsCat.add(new RedCat()); // Note that extendscat.add (null) can be compiled;Copy the code
Note that the
extends T> extends T> extends T> extends T> extends T> extends T
2. Now,
, which is the same as
is the opposite. The
a, a can accept a set of T and its T superclass, bound by T, and any type fetched from a will be cast to Object. Focus on the following example:
List<Animal> animals = new ArrayList<>(); List<Cat> cats = new ArrayList<>(); List<RedCat> redCats = new ArrayList<>(); // You can compile List<? super Cat> superCat = animals; // Cannot compile because only Cat and its superclass superCat = redCats are accepted; Supercat.add (new Animal()); supercat.add (new Animal()); Supercat.add (new Cat()); superCat.add(new RedCat()); superCat.add(null);Copy the code
Notice that
The most important thing to note is that although we can accept T and its superclass assignment, we can only add T and its subclasses to it.
conclusion
1, the List
a extends T> a extends T> a extends T> A extends T> A extends T> A extends T> A extends T> A.
2, the List
a, we can assign a and its superclass to A. All elements from A are cast to Object. However, we need to note that we can add elements to A, but only T and its subclass elements.
3. Generics vs. overloading
Let’s start with a question. Do you think this one will compile?
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"); }}Copy the code
Answer: Failed to compile.
The two methods have different parameters. Why would overloading not pass?
In fact, in Java generics, generics exist only in the source code; in the compiled bytecode, generics have been replaced with native types, and cast code has been inserted in place. To help you understand, take a look at the following code example:
Public static void main(String[] args) {List<Integer> List = new ArrayList<>(); list.add(1); System.out.println(list.get(0)); }Copy the code
After compiling, the generics are gone, and the cast code is inserted in place. After compiling, we decompiled the code as follows:
Public static void main(String[] args) {List List = new ArrayList(); list.add(1); System.out.println((Integer)list.get(0)); }Copy the code
After this compilation, the generics are gone, and a mechanism for casting code is inserted in place, also known as erasing.
So the above two methods seem to have different parameters, but after compilation and erasable, their parameters are the same, so the compilation fails.
4. Points needing attention when converting between arrays and collections
1, array to set
So let’s start with an example,
public static void main(String[] args) {
String[] arr = {"one"."two"."three"}; List<String> List = arrays.aslist (arr); // Add elements to collection: Compile fine, but run time throws exception list.add("four");
}
Copy the code
Adding an element to the collection throws the following exception:
Why does adding an element to a collection throw an exception?
Let’s look at what the arrays.aslist (arR) method returns.
The source code is as follows:
The return is an ArrayList, why can’t you add elements?
In fact, this ArrayList is not that ArrayList, and the returned ArrayList is actually an inner class of Arrays. This inner class is also very simple, and the real ArrayList is no comparison, part of the source:
And the fake ArrayList is a direct reference to the original array, otherwise look at its constructor (second underlined)
That is, inside an ArrayList is a direct reference to an ARR array, and if you change the ARR array, you also change the list.
The following code proves this
public static void main(String[] args) {
String[] arr = {"one"."two"."three"}; List<String> List = arrays.aslist (arr); // Modify arr arr[0] ="0"; System.out.println(list.get(0)); }Copy the code
The printed result is “0”.
So, we’re going to fail to add elements to the list, because the arR array is 3, so there are already 3 elements, and you’re adding a fourth element to it, so it’s not going to work.
So, when converting an array to a collection, you need to be careful.
It is recommended that this conversion is safer
List<String> list = new ArrayList<>(Arrays.asList(arr));
Copy the code
2. Set to array
Collection to array conversion is relatively easy, I won’t pull a lot of source code to analyze, I will just briefly mention a few points need to pay attention to. For example, for the following transformation:
List<String> List = new ArrayList<>(); // Array String of length n [] arr = new String[n]; // Convert list.toarray (arr);Copy the code
1. If the array size is smaller than the collection size: since the arR size is insufficient, the elements in the collection will not be assigned to the ARR, and a new array will be created.
2. If the array length is not smaller than the collection: the arR length is sufficient, so the elements in the collection are copied directly to the ARR array without creating a new element.
At a glance source:
public <T> T[] toArray(T[] a) {
if(a.length < size) // Create a new array to return toreturn(T[]) Arrays.copyOf(elementData, size, a.getClass()); Arraycopy (elementData, 0, a, 0, size);if (a.length > size)
a[size] = null;
return a;
}
Copy the code
I believe that many people do not know these traps, I summarized it sorted out, I hope you can have a harvest after reading.
Below I summarized sets, generics, array rotation sets and other common traps, carefully read, I believe you will definitely gain.
If you find this article inspiring, go ahead
1, like, so that more people can see this content (collection does not like, are playing rogue -_-)
Focus on me, let’s become a long-term relationship
3. Follow the public account “Helpless and painful code Farmer”, which has more than 100 original articles, I also share a lot of video, book resources, and development tools, welcome your attention, the first time to read my article.