? Wildcard type
- ## extends T> indicates the upper bound of the type, indicating that the parameterized type may be T or a subclass of T;
- super T> represents the lower bound of the type (called super type qualification in Java Core), indicating that the parameterized type is the super type (parent type) of this type, until Object;
The upper bound A collection of all classes of T. You may think that the List you define can be used to put any subclass of T. Then let’s look at the following code:
import java.util.LinkedList;
import java.util.List;
public class test {
public static void main(String[] args) {
List<? extends Father> list = new LinkedList<>();
list.add(new Son());
}
}
class Human{
}
class Father extends Human{
}
class Son extends Father{
}
class LeiFeng extends Father {
}
Copy after login
list.add(new Son()); This line will report an error: The method put(Son) is undefined for the type List
List extends Father> means "a list with any type inherited from Son" , the compiler cannot determine the type held by the List, so it cannot safely add objects to it. You can add null because null can represent any type. So the add method of List cannot add any meaningful elements, but it can accept existing subtype List assignments. You may try to do this: List<? extends Father> list = new LinkedList<Son>();
list.add(new Son());
Copy after login
Even if you specify the Son type, you cannot add a Son object using the add method. Why can't the Father class and the subclasses of the Father class be added to the list? Let's analyze it. List extends Father> means that the upper limit is Father, and the following assignments are legal List<? extends Father> list1 = new ArrayList<Father>();
List<? extends Father> list2 = new ArrayList<Son>();
List<? extends Father> list3 = new ArrayList<LeiFeng>();
Copy after login
If List extends Father> supports the add method: list1 can add Father and all subclasses of Father; The reason is that the compiler only knows that the container is Father or its derived class, but it does not know the specific type. . Maybe Father? Maybe Son? Maybe LeiFeng, XiaoMing? After the compiler sees that Father is used for assignment later, the parameter type in the collection is not limited to "Father". Instead, it is marked with a placeholder: CAP#1 to indicate capturing a Father or a subclass of Father. I don’t know the specific class, but the code is CAP#1. Then whether you want to insert Son, LeiFeng or Father compiler, you don't know whether it can match this CAP#1, so you won't allow it. So the difference between wildcard > and type parameters is that to the compiler, all T represents the same type. For example, in the following generic method, the three T's all refer to the same type, either String or Integer. public <T> List<T> fill(T... t);
Copy after login
But the wildcard > does not have such a constraint. List> simply means: there is something in the collection, and I don’t know what it is. So the error here is that nothing can be put in List extends Father>. List extends Father> list cannot be added, but this form is still very useful. Although the add method cannot be used, a Season can specify different types during initialization. For example: List<? extends Father> list1 = getFatherList();//getFatherList方法会返回一个Father的子类的list
Copy after login
In addition, since we have ensured that the Father class or one of its subclasses is stored in the List, you can use the get method to directly obtain the value: List<? extends Father> list1 = new ArrayList<>();
Father father = list1.get(0);//读取出来的东西只能存放在Father或它的基类里。
Object object = list1.get(0);//读取出来的东西只能存放在Father或它的基类里。
Human human = list1.get(0);//读取出来的东西只能存放在Father或它的基类里。
Son son = (Son)list1.get(0);
Copy after login
Lower bound< ;? super T> does not affect storage in, but retrieval can only be placed in the Object object. The lower bound is declared with super, indicating that the parameterized type may be the specified type, or this type Parent type, up to Object. //super只能添加Father和Father的子类,不能添加Father的父类,读取出来的东西只能存放在Object类里
List<? super Father> list = new ArrayList<>();
list.add(new Father());
list.add(new Human());//compile error
list.add(new Son());
Father person1 = list.get(0);//compile error
Son son = list.get(0);//compile error
Object object1 = list.get(0);
Copy after login
Because the lower bound specifies the lower limit of the minimum granularity of the element, it actually relaxes the type control of the container element. Since the element is the base class of Father, it can be stored in a granularity smaller than that of Father. For type safety reasons, we can add a Father object or any of its subclasses (such as Son). However, since the compiler does not know which superclass of Father the content of the List is, it is not allowed to add any specific superclass. Class (such as Human). And when we read it, the compiler can only return the Object object without knowing what type it is, because Object is the ultimate ancestor class of any Java class. But in this case, all the type information of the element is lost. PECS PrincipleFinally, let’s take a look at what is the PECS (Producer Extends Consumer Super) principle. It is already well understood:
Frequent external reading For content, it is suitable to use the upper bound Extends.
-
If you often insert it in, Nether Super is suitable.
The above is the detailed content of What are extends T and super T in Java?. For more information, please follow other related articles on the PHP Chinese website!