Maison > Java > javaDidacticiel > le corps du texte

Que sont les extensions T et super T en Java ?

PHPz
Libérer: 2023-05-09 11:19:17
avant
1304 Les gens l'ont consulté

? Le type générique

  • représente la limite supérieure du type, indiquant que le type paramétré peut être T ou une sous-classe de T. ;

  • représente la limite inférieure du type (appelée qualification de super type dans Java Core), indiquant que le type paramétré est le super type (type parent ) de ce type, jusqu'à ce que l'objet ;

upperboundTout d'abord, vous pouvez facilement le comprendre comme un ensemble de toutes les classes. qui héritent de T. Vous pensez peut-être que la liste que vous définissez peut être utilisée pour mettre n'importe quelle sous-classe de T, alors regardons le code suivant : #🎜 🎜#
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 {
}
Copier après la connexion

list.add(new Son()); Cette ligne signalera une erreur : La méthode put(Son) n'est pas définie pour le type List

#🎜 🎜#List hérité de Son". Le compilateur ne peut pas déterminer le type détenu par List, il ne peut donc pas y ajouter d'objets en toute sécurité. Vous pouvez ajouter null car null peut représenter n'importe quel type. Ainsi, la méthode add de List ne peut ajouter aucun élément significatif, mais elle peut accepter les affectations de sous-types List existantes.

Vous pouvez essayer de faire ceci :

List<? extends Father> list = new LinkedList<Son>();
list.add(new Son());
Copier après la connexion

Même si vous spécifiez le type Son, vous ne pouvez pas ajouter d'objet Son à l'aide de la méthode add.

Pourquoi la classe Père et les sous-classes de la classe Père ne peuvent-elles pas être ajoutées à la liste ?

List signifie que la limite supérieure est Father, et les affectations suivantes sont légales

   List<? extends Father> list1 = new ArrayList<Father>();
   List<? extends Father> list2 = new ArrayList<Son>();
   List<? extends Father> list3 = new ArrayList<LeiFeng>();
Copier après la connexion

If List

list1 peut ajouter Père et toutes les sous-classes de Père ;

  • list2 peut ajouter Fils et toutes les sous-classes de Fils La classe

  • list3 peut ajouter LeiFeng et toutes les sous-classes de LeiFeng.

  • Le code suivant ne parvient pas à se compiler :

    list1.add(new Father());//error
    list1.add(new Son());//error
    Copier après la connexion

    La raison est que le compilateur sait seulement que le conteneur est Father ou sa classe dérivée, mais je ne sais pas de quel type il s'agit spécifiquement. Peut-être Père ? Peut-être mon fils ? Peut-être LeiFeng, XiaoMing ? Une fois que le compilateur voit que Père est utilisé pour une affectation ultérieure, le type de paramètre dans la collection n'est pas limité à « Père ». Au lieu de cela, il est marqué d'un espace réservé : CAP#1 pour indiquer la capture d'un Père ou d'une sous-classe de Père. Je ne connais pas la classe spécifique, mais le code est CAP#1. Ensuite, que vous souhaitiez insérer le compilateur Son, LeiFeng ou Father, vous ne savez pas s'il peut correspondre à ce CAP#1, vous ne l'autoriserez donc pas.
Donc, la différence entre les paramètres génériques et les paramètres de type est que pour le compilateur, tous les T représentent le même type. Par exemple, dans la méthode générique suivante, les trois T font tous référence au même type, soit String, soit Integer.

public <T> List<T> fill(T... t);
Copier après la connexion

Mais le caractère générique n'a pas une telle contrainte List

Donc l'erreur ici est que rien ne peut être mis dans List

List ne peut pas être ajouté, mais ce formulaire est toujours très utile Bien que la méthode add ne puisse pas être utilisée, une saison peut spécifier différents types lors de l'initialisation. Par exemple :

List<? extends Father> list1 = getFatherList();//getFatherList方法会返回一个Father的子类的list
Copier après la connexion

De plus, puisque nous nous sommes assurés que la classe Father ou une de ses sous-classes est stockée dans la List, vous pouvez utiliser la méthode get pour obtenir directement la valeur :

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);
Copier après la connexion
#🎜 🎜#Lowerbound n'affecte pas le stockage dans, mais la récupération ne peut être placée que dans l'objet Object

La limite inférieure est déclarée avec super, indiquant que le type paramétré peut être le type spécifié, ou un type parent de ce type, jusqu'à 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);
Copier après la connexion

Étant donné que la limite inférieure spécifie la limite inférieure de la granularité minimale de l'élément, elle assouplit en fait le contrôle de type de l'élément conteneur. Puisque l’élément est la classe de base de Father, il peut être stocké dans une granularité plus petite que celle de Father. Pour des raisons de sécurité de type, nous pouvons ajouter un objet Father ou l'une de ses sous-classes (telles que Son). Cependant, comme le compilateur ne sait pas à quelle superclasse de Father appartient le contenu de la liste, il n'est pas autorisé à ajouter une superclasse spécifique. . Classe (comme Humain). Et lorsque nous le lisons, le compilateur ne peut renvoyer que l'objet Object sans savoir de quel type il s'agit, car Object est la classe ancêtre ultime de toute classe Java. Mais dans ce cas, toutes les informations de type de l’élément sont perdues.

Principe PECS

Enfin, regardons ce qu'est le principe PECS (Producer Extends Consumer Super), déjà bien compris :

#🎜🎜 #

Si vous lisez fréquemment du contenu de l'extérieur, il convient d'utiliser la limite supérieure Extends.

Il convient d'utiliser Nether Super si vous l'insérez souvent.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:yisu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal