Découvrez comment Java protège l'intégrité des types

quoi

―― À la suite de l'utilisation de PHP pendant plusieurs années, ma connaissance de Java a diminué, je vais donc la rappeler et la résumer (principalement sur la partie compliquée du type)

Qu'est-ce qui était immuable et co-changé?

--Assomption) Quand le chien étend l'animal --Séquence est covariante) Chien [] est un sous-type d'Animal [](= assignable)

Quelle était la marque, T, étend, etc. apparaissant dans la déclaration de la classe ou de la méthode?

--Une classe qui a un paramètre de type (tel que T) dans sa déclaration est appelée une classe générique.

class Animal {
    public int getAge() {
        return 3;
    }
}

class Dog extends Animal {
    @Override
    public int getAge() {
        return 33;
    }
    //Méthodes uniquement dans la classe Dog
    public String getName() {
        return "john";
    }
}

class AnimalBox<T extends Animal> {
    T someAnimal;
    
    public AnimalBox(T animal) {
        someAnimal = animal;
    }
    
    public int getAge() {
        return someAnimal.getAge();
    }
}

―― ~~ Cependant, dans ce cas, si vous le faites simplement de type Animal, vous pouvez insérer Dog et faire de même, donc je ne sais pas comment l'utiliser correctement (c'est un problème) ~ ~ ――Pour le problème ci-dessus, si vous implémentez public T get (), le type générique peut être retourné par Dog, mais AnimalBox2 ne peut renvoyer que Animal.Dans le commentaire, j'ai expliqué un exemple de la différence.

//C'est bon
class AnimalBox2 {
    Animal someAnimal;
    
    public AnimalBox2(Animal animal) {
        someAnimal = animal;
    }
    
    public int getAge() {
        return someAnimal.getAge();
    }
}
class Box<T> {
    T someValue;
    List<T> history = new ArrayList<>();
    
    public Box(T v) {
        someValue = v;
    }
    
    public T get() {
        return someValue;
    }
    
    public void selectOne(Box<? extends T> box) {
        history.add(box.get());
    }
}

Que signifie oublier le type générique et l'assigner à une sous-classe?

    Dog d = new Dog();
    Animal a = d; //Bien qu'il s'agisse d'un type différent, il peut être attribué car il s'agit d'une sous-classe
        
    System.out.println(a.getClass().getName()); //Dog
    System.out.println(a.getAge()); //33
    System.out.println(d.getName()); //john
    System.out.println(a.getName()); //error: cannot find symbol

--D'en haut)

SpaceDog sd = new Dog(); //Dog cannot be converted to SpaceDog

Que signifie l'immuabilité de type générique?

―― Et si le type générique est covariant?

        List<SpaceDog> spaceDogList = new ArrayList<>();
        List<Dog> dogList = spaceDogList; //(Si c'était un co-changement)Bien qu'il s'agisse d'un type différent, il peut être attribué car il s'agit d'une sous-classe
        dogList.add(new Dog());

--Dog a entré List \ via la variable dogList. C'est un problème lors de l'utilisation de spaceDogList. Il est immuable d'empêcher cela. --En fait, erreur de compilation: List \ ne peut pas être converti en List \

Pourquoi les séquences sont-elles covariantes?

«Ce n'est pas devenu. Cela n'entraîne pas d'erreur de compilation, mais une erreur d'exécution.

        SpaceDog[] spaceDogArray = new SpaceDog[1];
        Dog[] dogArray = spaceDogArray;
        dogArray[0] = new Dog(); //Erreur d'exécution:java.lang.ArrayStoreException: Dog

N'est-ce pas la même chose pour les classes ordinaires qui ne sont pas des types génériques que la variable a une référence à l'entité et que son interprétation dans l'héritage de classe diffère selon la situation?

――Vous ne comprenez peut-être pas ce que vous dites ―― ↓ Dans un tel cas, la variable a peut-elle être utilisée pour détruire la composition type?

        Dog d = new Dog();
        Animal a = d;
        //Je veux en quelque sorte utiliser la variable a pour que la variable d soit en difficulté pour la commodité de l'interprétation des types.

«Je ne peux penser qu'à créer et à écraser, mais d n'est pas un problème car il n'est pas écrasé et est créé dans un autre emplacement.

        Dog d = new Dog();
        Animal a = d;
        System.out.println(d); //Dog@77468bd9 
        System.out.println(a); //Dog@77468bd9
        a = new Animal();
        System.out.println(a); //Animal@12bb4df8

Organisation de la relation entre les types génériques et les paramètres de type

        List<Dog> dogList = new ArrayList<>();
        dogList.add(new Dog());
        dogList.add(new SpaceDog());

――Je ne peux pas faire ça

class Box<T> {
    T someValue;
    List<T> history = new ArrayList<>();
    
    public Box(T v) {
        someValue = v;
    }

    public void set(T v) {
        someValue = v;
    }
    
    public T get() {
        return someValue;
    }
    
    public void selectOne(Box<T> box) {
        history.add(box.get());
    }
}

Box<Dog> dogBox = new Box<>(new Dog());
Box<SpaceDog> spaceDogBox = new Box<>(new SpaceDog());
dogBox.selectOne(spaceDogBox); //Erreur de compilation:Box<Dog>Et boîte<SpaceDog>Est un autre type

――Vous pouvez le faire de cette façon

    public void selectOne(Box<? extends T> box) {
        history.add(box.get());
    }

――Pourquoi le type est-il cohérent? --Il est interdit de transmettre une valeur autre que null à la méthode set (si Dog peut être défini, someValue of Box \ deviendra Dog)


    public void selectOne(Box<? extends T> box) {
        history.add(box.get());
        box.set(someValue); //Erreur de compilation
    }

Qu'est-ce que \ <? Super T>?

--Si vous pensez que \ <? Etend T> ci-dessus "soulage (de manière covariante) l'invariance des types génériques en limitant la fonction des variables pour récupérer les valeurs"

Résumé

――Si une classe normale résume les attributs et les comportements d'objets spécifiques (animaux, chiens, etc.), le type générique est imaginé comme enveloppant le résumé *** dans un contexte différent. Faire --Il y a deux mondes, l'un est le monde des classes normales (Animal, Dog, SpaceDog) qui sont des paramètres de type, et l'autre est le monde des contextes (List, Queue, Box, Optional ...) que les types génériques tentent d'exprimer. --Les actions de "donner une valeur au contexte" et "récupérer la valeur du contexte" se produisent, mais si elle reste inchangée, la relation d'héritage des paramètres de type ne peut pas être utilisée, il y a donc de grandes restrictions.

Diagramme de modèle

java.png

Recommended Posts

Découvrez comment Java protège l'intégrité des types
Comment trouver les nombres premiers Java
Comment utiliser le type enum Java
Comment savoir quelle version Java d'un fichier de classe a été compilée
Conversion de type Java
[Java] Type d'énumération
Java Type facultatif
Java double type
java: Comment écrire une liste de types génériques [Note]
[Java] Comment découper une chaîne de caractères caractère par caractère
J'ai essayé de découvrir ce qui avait changé dans Java 9
[Java] Type de données ①-Type de base
Découvrez Docker
[Java, Kotlin] Variance de type
Champ de type de classe Java
Détermination de type en Java
Étudier Java # 1 (type typique)
Comment repousser la barre oblique \
[Java] Conversion de type de date
Trouvez la classe d'adresse et le type d'adresse à partir de l'adresse IP avec Java
Différence entre Java et JavaScript (comment trouver la moyenne)
Découvrez tous les ID de fuseau horaire pris en charge par la classe Java TimeZone