First two pieces of code:
public static <T> void show1(List<T> list){ for (Object object : list) { System.out.println(object.toString()); } } public static void show2(List<?> list) { for (Object object : list) { System.out.println(object); } }
You can see that we use T in the show1 method. Everyone knows that this is a common way of writing generics, so T here refers to a certain type of specific Objects and list collections can only store data of the same type. If different types of data are inserted, an error will be reported.
So what do we use in the show2 method? , you can see that there is no <T>
in front of void,? It can be expressed as a placeholder, and it does not know how many types of data will be stored in the list collection, so this shows that it is also possible to store N data types in our list.
Let’s intuitively feel the difference between the two through a piece of test code:
public static void test(){ List<Student> list1 = new ArrayList<>(); list1.add(new Student("zhangsan",18,0)); list1.add(new Student("lisi",28,0)); list1.add(new Student("wangwu",24,1)); //这里如果add(new Teacher(...));就会报错,因为我们已经给List指定了数据类型为Student show1(list1); System.out.println("************分割线**************"); //这里我们并没有给List指定具体的数据类型,可以存放多种类型数据 List list2 = new ArrayList<>(); list2.add(new Student("zhaoliu",22,1)); list2.add(new Teacher("sunba",30,0)); show2(list2); }
Let’s take a look at the running results:
Student{name='zhangsan ', age=18, sex=0}
Student{name='lisi', age=28, sex=0}
Student{name='wangwu', age=24, sex=1}
************Separation line******************
Student{name='zhaoliu', age=22, sex=1}
Teacher{name='sunba', age=30, sex=0}
You can see the difference from show1 from the show2 method. List2 stores two types of Student and Teacher. The same can be done Output data, so this is the difference between T and ?~ Friends, do you understand?
Let’s take a look? Extended writing method:
List<? extends data type> list
public static void show3(List<? extends Teacher> list) { for (Object object : list) { System.out.println(object); } }
List<? extends Teacher> list
This writing method means that it can Receive a list collection of Teacher and its subclass data types, and write a test method show3(list2);
Try:
Student{name='zhaoliu', age=22, sex=1} Teacher{name='sunba', age=30, sex=0}
You can see normal output, because the data in the collection are all It is a subclass type of Teacher. What will happen if we change List<? extends Teacher> list
to List<? extends Student> list
?
Look at this picture carefully. We have created a new list3 and declared the data type to be Teacher. At this time, we call show3(List<? extends Student> list)
An error will be reported immediately. The error message indicates that Teacher cannot be converted to Student, because Student is a subclass of Teacher, and we only accept Student and its subclasses, so of course an error will be reported.
List<? super data type> list
This way of writing means that only the specified data type and its parent class type are received, and it is also a simple way to write a piece of code Take a look at the effect:
public static void show4(List<? super Student> list) { for (Object object : list) { System.out.println(object); } }
It can be seen that what we receive is the collection of Student and its parent class. We write two collection data and then call it to try.
List list4 = new ArrayList<>(); list4.add(new Student("sunba",30,0)); list4.add(new Teacher("zhaoliu",22,1)); show4(list4);
Insert a Student and Teacher object into the list and see the result:
Student{name='sunba', age=30, sex=0} Teacher{name='zhaoliu', age=22, sex=1}
Nothing wrong, it runs normally and outputs.
Let’s take a look at what will happen if we pass a collection of Student subclasses
You can see the same as before, it will The error is reported for the same reason, thinking that we have defined a data type that can only receive Student and its parent class.
Finally let’s look at a situation
If I don’t specify a data type when defining List, and insert a Child, Student, Teacher, or call show4(List super Student> list)
, will an error be reported? If no error is reported, what will be the result?
You can see that no error is reported because list can store multiple data types. So what will be the result when calling the show4 method?
You can see that the program runs normally and outputs results. Note that what we receive is the Student and its parent class object data types, because our Child inherits from Student. Therefore, the program automatically converts our Child into the parent class Student for output, so everyone should pay attention to this, and it will automatically convert upward.
The above is the detailed content of What are the differences between placeholders T and ? in java generics?. For more information, please follow other related articles on the PHP Chinese website!