[JavaSE] Ces choses sur les génériques (archéologie générique, effacement générique, classes wrapper)

insérez la description de l'image ici
J'espère communiquer et apprendre les uns des autres à travers le blog. S'il y a des erreurs, veuillez me corriger dans la zone de commentaires.

1. Qu'est-ce que les génériques

L'essence du type générique est de paramétrer le type, c'est-à-dire que le type de données à exploiter est spécifié en tant que paramètre. Ce type de paramètre peut être utilisé dans la création de classes, d'interfaces et de méthodes, appelées classes génériques, Interface générique, méthode générique.

2. Pourquoi avoir des génériques ?

J'ai déjà écrit la table de séquence MyArrayList. Cette classe ne peut être représentée que par un seul type lorsqu'elle est implémentée, c'est-à-dire que lorsqu'elle est utilisée, la MyArrayList implémentée par elle-même ne peut être appliquée qu'à un type. Si vous souhaitez l'appliquer à autres types, vous devez écrire un autre type de MyArrayList, ce qui est plus gênant, mais avec des génériques, ce problème peut être très bien résolu, et le type est paramétré, de sorte que le MyArrayList écrit par vous-même puisse être appliqué à divers scénarios.

La commodité des génériques peut être trouvée grâce à la comparaison de code suivante

Exemple

sans génériques

public class MyArrayList {
    
    
    private int[] array;
    private int size;    // 有效数据个数
    public MyArrayList() {
    
    
        this.array = new int[10];
        this.size = 0;
    }
    public void add(int x) {
    
        // 暂不考虑扩容
        this.array[size] = x;
        this.size++;
    }
}

avec des génériques

import org.omg.CORBA.Object;

public class MyArrayList2<E> {
    
    
    // 在类的实现中,可以直接将类当成一种数据类型来使用。在实例化该类的时候这个类型才被确定
    private E[] array;
    private int size;   // 有效数据个数
    public MyArrayList2() {
    
    
        this.array = (E[])new Object[10];   // 注意:Java中泛型不允许定义数组
        this.size = 0;
    }
    public void add(E e) {
    
        // 不考虑扩容
        this.array[size] = e;
        this.size++;
    }
}
// 带泛型的顺序表元素类型是一个“变量”
// E就是变量的名称

En comparant les deux morceaux de code ci-dessus, on peut constater que la table de séquence avec des génériques et la table de séquence sans génériques ne sont différentes que dans la partie du type, et la logique implémentée par le code est la même

Instanciation et utilisation des classes

public static void main(String[] args) {
    
    
    MyArrayList myArrayList = new MyArrayList();
    myArrayList.add(1);
    myArrayList.add(2);
																	// 这里其实就相当于是将String类型赋值给E
    MyArrayList2<String> stringMyArrayList2 = new MyArrayList2<String>();    // 等号右边的<>内可以省略
    stringMyArrayList2.add("1");                                           // 要想用基本类型,要写基本类型对应的包装类
    stringMyArrayList2.add("2");
}

Pour les génériques, le type est explicitement défini lorsque la classe est utilisée

3. Archéologie générique

Vous devez savoir qu'il n'y avait pas de type générique dans le système Java au début, et ce n'est qu'après JDK1.5 qu'il y a eu un type générique.

Avant JDK1.5, les références d'objet peuvent être utilisées pour pointer vers des objets de tout type afin d' obtenir des effets génériques

  1. La classe d'objet est la classe ancêtre de toutes les classes
  2. Les références de niveau supérieur peuvent pointer vers des objets de niveau inférieur

Le code suivant :

public class MyArrayList3 {
    
    
    private Object[] array;
    private int size;
    public MyArrayList3() {
    
    
        this.array = new Object[10];
        this.size = 0;
    }
    public void add(Object e) {
    
    
        this.array[size] = e;
        size++;
    }
}

L'inconvénient de cette approche est également évident, c'est-à-dire qu'une nouvelle MyArrayList est créée, qui est destinée à stocker des données de type int, mais en raison du glissement, une donnée de type String est stockée, de sorte que le compilateur ne signalera pas une erreur , et le programme peut également Il s'exécute normalement et le programme ne lèvera pas d'exception tant qu'il n'aura pas besoin de récupérer les éléments de la liste.

Les génériques résolvent très bien ce problème. Tant que les types ne correspondent pas, l'erreur sera exposée la première fois

Quatrièmement, l'effacement générique

Bien qu'il existe des génériques après JDK1.5, l'implémentation sous-jacente de JDK est toujours implémentée avec l'objet ci-dessus.

Comme le montre la figure ci-dessous
[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leech, il est recommandé d'enregistrer l'image et de la télécharger directement (img-sB60DwZz-1646265098596) (C:\Users\LY\AppData\Roaming\Typora\typora -images-utilisateur\image-20211210185132787.png)]
, bien que nous utilisions des génériques, en fait, les génériques n'existent que dans la phase de compilation, et le processus de compilation s'accompagne également d'un effacement générique. Lorsque le .classfichier est généré, l'information générique n'existe plus, et elle devient JDK1. Méthode d'objet avant 5

En regardant le fichier bytecode de MyArrayList, vous pouvez voir
[Échec du transfert d'image du lien externe, le site source peut avoir un mécanisme anti-leech, il est recommandé d'enregistrer l'image et de la télécharger directement (img-KCvl7iYr-1646265098598) (C:\Users\LY\AppData\Roaming\Typora\typora -images-utilisateur\ image-20220123202400988.png)]
que les génériques de Java n'existent que dans la phase de compilation (principe de base de Java : les références d'objet peuvent pointer vers n'importe quel type d'objet)

Cinq, emballage

Étant donné que les 8 types de base ne sont pas des types, Java définit leurs propres classes wrapper spécifiquement pour eux

comme suit:

byte          java.lang.Byte
short         java.lang.Short
char          java.lang.Character
int           java.lang.Integer
long          java.lang.Long
float         java.lang.Float
double        java.lang.Double
boolean       java.lang.Boolean

6. Emballage et déballage

[Échec du transfert d'image du lien externe, le site source peut avoir un mécanisme anti-leech, il est recommandé d'enregistrer l'image et de la télécharger directement (img-dsPrxxd0-1646265098599) (C:\Users\LY\AppData\Roaming\Typora\typora -images-utilisateur\ image-20220212173816723.png)]
La commodité est fournie en Java. S'il n'y a pas d'ambiguïté, Java emballera et déballera automatiquement pour nous.

Integer a = 10;   // 把int赋值给Integer类型,隐含着发生了装箱过程
int b = a;      // 把Integer赋值给int类型,隐含着发生了拆箱过程

Le processus de boxing et unboxing implicite n'existe que dans la phase de compilation. Une fois la compilation terminée, il devient boxing explicite et unboxing explicite.

Je suppose que tu aimes

Origine blog.csdn.net/weixin_46531416/article/details/123244588
conseillé
Classement