Deux premiers morceaux de 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); } }
Vous pouvez voir que nous utilisons T dans la méthode show1 Tout le monde sait que c'est une façon courante d'écrire des génériques, donc T fait ici référence à un certain. Les objets spécifiques à une classe ne peuvent stocker que des données du même type dans la collection de listes. Si différents types de données sont insérés, une erreur sera signalée.
Alors qu'est-ce qu'on utilise dans la méthode show2 ? , vous pouvez voir qu'il n'y a pas de <T>
devant void ? Il peut être exprimé sous forme d'espace réservé et il ne sait pas combien de types de données seront stockés dans la collection de listes, cela montre donc qu'il est également possible de stocker N types de données dans notre liste. <T>
,?可以表示成占位符,它自己也不知道list集合中会存放多少种类型的数据,所以这样就表明我们的list中存放N种数据类型也是可以的。
我们通过一段测试代码来直观的感受一下二者的区别吧:
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); }
来看看运行结果:
Student{name='zhangsan', age=18, sex=0}
Student{name='lisi', age=28, sex=0}
Student{name='wangwu', age=24, sex=1}
************分割线**************
Student{name='zhaoliu', age=22, sex=1}
Teacher{name='sunba', age=30, sex=0}
从show2方法可以看出和show1的区别了,list2存放了Student和Teacher两种类型,同样可以输出数据,所以这就是T和?的区别啦~小伙伴们了解了吧
下面来看看?的扩展写法:
List<? extends 数据类型> list
public static void show3(List<? extends Teacher> list) { for (Object object : list) { System.out.println(object); } }
List<? extends Teacher> list
这种写法表示可以接收Teacher和它的子类数据类型的list集合,写个测试方法show3(list2);
试试:
Student{name='zhaoliu', age=22, sex=1} Teacher{name='sunba', age=30, sex=0}
可以看到正常输出,因为集合中的数据都是Teacher的子类类型,如果我们将List<? extends Teacher> list
改成List<? extends Student> list
会出现什么情况?
仔细看这张图,我们新建了一个list3并且声明数据类型为Teacher,这个时候调用show3(List<? extends Student> list)
就马上会报错的,错误信息提示Teacher不能转换成Student,因为Student是Teacher的子类,而我们只接受Student及它的子类,所以当然会报错了。
List<? super 数据类型> list
这种写法表示只接收指定的数据类型及它的父类类型,也简单的写段代码看看效果:
public static void show4(List<? super Student> list) { for (Object object : list) { System.out.println(object); } }
可以看出来,我们接收的是Student及它父类的集合,我们写两个集合数据然后调用试试。
List list4 = new ArrayList<>(); list4.add(new Student("sunba",30,0)); list4.add(new Teacher("zhaoliu",22,1)); show4(list4);
在list中插入了一个Student和Teacher对象,看看结果:
Student{name='sunba', age=30, sex=0} Teacher{name='zhaoliu', age=22, sex=1}
没毛病,正常运行并输出。
下面我们来看看,如果我们是传递的 Student的子类的集合会咋样
可以看到和之前的一样,会报错,理由也是一样的,以为我们已经定义了只能接收Student及其父类的数据类型。
最后来看一种情况
如果我定义List的时候没有指定数据类型,并且插入了一个Child,Student,Teacher,还是调用show4(List super Student> list)
rrreee Jetons un coup d'œil aux résultats en cours :
#🎜 🎜# Étudiant{name='zhangsan', age=18, sex=0}Vous pouvez voir la différence entre show1 et la méthode show2, list2 stocke deux types : Étudiant et Enseignant, et peut également générer des données, c'est donc la différence entre T et ?~ Les amis, comprenez-vous
Étudiant{name='lisi', age=28, sex=0}
Étudiant{name='wangwu', age= 24, sex=1}
************Ligne de séparation***************
Étudiant{name='zhaoliu ', age=22, sex=1}
Professeur{name='sunba', age=30, sex=0}
Jetons un coup d'oeil ? Méthode d'écriture étendue :
List étend la liste des types de données>
List Cette façon d'écrire signifie que vous pouvez recevoir une liste de types de données Teacher et ses sous-classes. Écrivez une méthode de test <code>show3(list2);
et essayez : #🎜🎜#rrreee#🎜🎜#Vous pouvez. voir Sortie normale, car les données de la collection sont toutes des sous-classes de Teacher. Si nous modifions List extends Teacher> en <code>List Ce qui se produit? #🎜🎜##🎜🎜#<img src="https://img.php.cn/upload/article/000/465/014/168379980974599.png" alt="Placeholder T et ? dans les génériques Java ? Que sont les différences?">#🎜🎜##🎜🎜#Regardez attentivement cette image. Nous avons créé une nouvelle liste3 et déclaré le type de données comme Enseignant. À ce stade, nous appelons <code>show3(List extends Student> list)
signalera immédiatement une erreur. Le message d'erreur indique que Teacher ne peut pas être converti en Student, car Student est une sous-classe de Teacher, et nous n'acceptons que Student et ses sous-classes, donc bien sûr, une erreur sera signalé. #🎜🎜##🎜🎜#List super data type> list
#🎜🎜##🎜🎜#Cette façon d'écrire signifie que seuls le type de données spécifié et son type parent sont reçus, et Écrivez simplement un morceau de code pour voir l'effet : #🎜🎜#rrreee#🎜🎜# On peut voir que ce que nous recevons est la collection de Student et de sa classe parent, écrivons deux collections de données puis appelons-la pour essayer. . #🎜🎜#rrreee#🎜🎜#Insérez un objet Étudiant et Enseignant dans la liste et voyez le résultat : #🎜🎜#rrreee#🎜🎜#Rien de mal, il fonctionne normalement et sort. #🎜🎜##🎜🎜#Voyons ce qui se passe si nous réussissons une collection de sous-classes d'étudiants#🎜🎜##🎜🎜##🎜🎜##🎜🎜#Vous pouvez voir la même chose qu'avant, une erreur sera signalée pour la même raison , pensant que nous avons défini un type de données qui ne peut recevoir que Student et sa classe parent. #🎜🎜##🎜🎜#Enfin, regardons une situation #🎜🎜##🎜🎜#Si je ne spécifie pas de type de données lors de la définition de la liste et que j'insère un enfant, un étudiant, un enseignant, j'appelle toujours show4 ( List super Student> list)
, une erreur sera-t-elle signalée ? Si aucune erreur n’est signalée, quel sera le résultat ? #🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#Vous pouvez voir qu'aucune erreur n'est signalée car la liste peut stocker plusieurs types de données. Alors, quel sera le résultat lors de l'appel de la méthode show4 ? #🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#Vous pouvez voir que le programme s'exécute normalement et affiche les résultats. Notez que ce que nous recevons sont les types de données de l'objet Student et de sa classe parent, car. notre enfant Il hérite de Student, donc le programme convertit automatiquement notre enfant en classe parent Student pour la sortie, donc tout le monde doit y prêter attention, et il sera automatiquement converti vers le haut. #🎜🎜#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!