Maison >Java >javaDidacticiel >Comment utiliser les méthodes génériques Java

Comment utiliser les méthodes génériques Java

王林
王林avant
2023-05-01 14:16:062640parcourir

Méthode générique

La définition générale est la suivante, c'est-à-dire qu'un est ajouté devant la méthode

public class FTest {
	public <t> List<t> f(T t){...};
}</t></t>

Trois méthodes d'inférence de paramètres génériques : #🎜🎜 #

1. Ajoutez le type générique déterminé directement devant f()

fTest.<integer>f(xxx)</integer>
2 Déterminez-le en saisissant des paramètres.

3. Il peut passer

Valeur de retour OK

int number = 0;
fTest.f(number)
Q : Quel est le problème avec le code ci-dessous ? Est-ce que toString() est là ?

List<integer> list = fTest.f(xxx);</integer>

A : test est une méthode statique, il ne peut donc pas détecter le T

dans l'instance A et doit être remplacé par

public static void test(T t)

toString() Il n'y a pas de problème, toString est la méthode de Object.

Paramètres génériques et élimination de type

Q : Que deviendra le paramètre générique T à l'exécution ?

A : Unifié en Objet et ne contient aucune information de type.


Q : L'instanceof peut-elle être utilisée pour comparer le paramètre générique T ?

public class A<t> {
	public static void  test(T t){
  		System.out.println(t.toString());  
  }
}</t>

A : Non, le compilateur signalera une erreur.

Q : Le paramètre générique T peut-il être utilisé avec new T() ou new T[] ?

A : Non, le compilateur signalera une erreur.


Comment utiliser les méthodes génériques JavaQ : Puis-je appeler des méthodes dans des objets à paramètres génériques ?

class A<t> {
   void f(Object arg)
   if(arg instanceof T) {
	  ...
   }
}</t>

A : Seules les méthodes de Object peuvent être appelées.

Q : T peut-il être utilisé pour une conversion forcée ?

T.f();

A : Il peut s'exécuter, mais la transformation ne se produira pas réellement et un avertissement sera déclenché lors de la compilation.

Questions lors de la création d'un nouvel objet générique

Supposons d'abord qu'il existe deux classes, la classe de base Parent et la sous-classe Enfant

T t = (T)object;

Répondez à la questions suivantes :

Q : Y a-t-il quelque chose qui ne va pas avec la phrase suivante ?

class Parent{}
class Child extends Parent{}

A : Il y a un problème, la compilation est fausse. Il n'y a pas de relation parent-enfant entre List et ArrayList

Q :

List<parent> list = new ArrayList<child>()</child></parent>

Quelles sont les caractéristiques de cette liste ?

A : Cette liste peut appeler A a = list.get(), mais ne peut pas list.add(new Parent())

    Raison : L'opération effectuée par
  • list.get() consiste à forcer l'extension interne de Parent> en Parent lors du retour, ce qui est raisonnable. Toute sous-classe de Parent peut être convertie en Parent#🎜 L'opération effectuée par 🎜#list.add(new Parent()) consiste à convertir le A externe en interne extend Parent>. Ceci est déraisonnable car nous ne savons pas si cet objet Parent peut être converti en quelle sous-classe Parent il devient.



    Q :
List extends Parent> list = new ArrayList<child>();</child>
Quelles sont les caractéristiques de cette liste ?

Qui signalera une erreur ci-dessous

List super Child> list = new ArrayList<parent>();</parent>

A : La capture d'écran est la suivante :

#🎜🎜 #Comment utiliser les méthodes génériques Java L'opération effectuée par Child c = list.get() ou Parent p = list.get() consiste à forcer le super Child> interne dans le parent ou l'enfant externe lors du retour, ce qui est déraisonnable car Le compilateur pense que la classe parent de l'enfant

    ne peut pas être convertie en parent ou en enfant, il interdit donc ce comportement (par exemple, la classe parent de parent est un objet, mais l'objet ne l'est pas. Il peut certainement être converti en parent ou en enfant). L'opération effectuée par *list.add(new Child()) consiste à convertir l'enfant ou le parent externe en super Child> interne lors de la saisie. Cela est raisonnable, car child et parent peuvent certainement être convertis en child . classe parente.
  • Q :

    list.add(new Child())
    list.add(new Parent())
    Parent a= list.get();
    Child b = list.get()
    Quelles sont les caractéristiques de cette liste ?

  • A : Ni get ni add ne peuvent être utilisés, seules des opérations telles que la suppression sans valeur de retour et sans entrée A peuvent être effectuées.
PS : Notez que cela ne signifie pas que vous ne pouvez pas appeler la méthode get ou add, mais lorsque vous appelez get ou add, vous ne pouvez pas utiliser l'objet A pour opérer.

C'est-à-dire que vous ne pouvez pas faire add(A) ou A a = get(0)

Mais vous pouvez faire add(object) ou Object o = get(0)

Parce que ? Il peut être converti en Objet, mais ne peut pas être converti en A.

Q : Le code suivant signalera-t-il une erreur ?

List> list = new ArrayList<a>();</a>

A : Aucune erreur ne sera signalée. Les résultats seront imprimés normalement.

Principe PECS

Faites attention à la différence entre le principe PECS et ce qui précède !

Le ? extend ou ? supert mentionné ci-dessus sont tous deux utilisés lors de la déclaration d'objets.

Le principe PECS est utilisé pour les paramètres d'entrée des méthodes des objets génériques ! Comment utiliser les méthodes génériques Java

Supposons qu'il existe une classe définie comme suit :

   List<fruit> fruitList = new ArrayList();
   fruitList.add(new Fruit());
   List<apple> appleList = new ArrayList();
   appleList.add(new Apple());
   fruitList.addAll(appleList);
   System.out.println(fruitList);</apple></fruit>

Alors T est le paramètre générique.

Q : Le code suivant peut-il s'exécuter normalement ?
public static class MyList<t> {
    List<t> list = new ArrayList();

    // 把输入参数塞给自己,类似于生产操作
    public void pushList(List<t> t) {
        list.addAll(t);
    }

    // 把自己的内容塞给输入参数,类似于让输入参数做消费。
    public void pollList(List<t> t) {
         t.addAll(list);
    }
}</t></t></t></t>

A : Il ne peut pas fonctionner normalement, pushList et pollList signaleront des erreurs

Parce qu'après la vérification du compilateur, il pense que List pas la même chose !

Q : Si nous voulons prendre en charge pushList ci-dessus, comment devons-nous modifier la définition de la méthode pushList ?

A : Remplacez-le par ceci :

MyList<number> myList = new MyList();

List<integer> intList = new ArrayList();
myList.pushList(intList);

List<object> objectList = new ArrayList();
myList.pollList(objectList);</object></integer></number>
Autrement dit, le compilateur pense que List et List 🎜🎜#Q : Si vous souhaitez supporter pollList, comment modifier la définition ?

A:

// 把自己的内容塞给输入参数,类似于让输入参数做消费。
public void pollList(List super T> t) {
    t.addAll(list);
}

因为是把自己的东西塞给输入参数, 而想要能塞进去,必须保证自己这个T,是输入参数的子类,反过来说,输入参数必须是T的父类,所以用super
于是编译器认为,List 和List super Number>是一个东西,允许!

PECS原则出自Effective Java, 注意只是一个编程建议而已!

  • 如果有一个类A,泛型参数为T

  • 如果他一般只用于接收输入容器List后,塞入自己内部的T容器, 则类A就叫生产者, 因此输入参数最好定义为 extend T>最好, 以便能接收任何T子类的容器。

  • 如果他一般只用于接收输入容器后List, 把自己内部的T元素塞给它, 那么这个类A就叫消费者, 输入参数最好定义为 super T>\ 最好, 以便自己的T元素能塞给任何T元素的父类容器。

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer