[JAVA] Comment penser quand on comprend soudainement les génériques

Aperçu

Les génériques sont des «arguments». Je vais résumer les pensées que j'ai pensé "Ah, je vois" quand je n'étais pas tout à fait sûr des génériques.

Site référencé

Merci pour la sagesse de nos prédécesseurs. http://d.hatena.ne.jp/Nagise/20101105/1288938415

Environnement Java

java version 1.8.0_181 Java(TM) SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

src └example   └java     └generics       ├ Main.java       └ GenericsSample.java

L'argument de valeur est la méthode, n'est-ce pas?

Parenthèses () ← C'est

La méthode est cette parenthèse (). Cette parenthèse () est le même symbole à la place de la déclaration de méthode et à la place de l'appel de méthode, mais elle est utilisée dans une signification différente. C'est une information pour indiquer "valeur utilisée dans la méthode".

Main.java


package example.java.generics;

public class Main {
    public static void main(String[] args) {
        int result = plus(2, 5); //ici  "()Déclare "La méthode sera exécutée avec la valeur de cet argument"(Argument réel)
        System.out.println(result);
    }

    public static int plus(int T, int S) { //ici "()Déclare "Je recevrai un argument avec ce nom d'argument"(Argument formel)
        return T + S;
    } // T,Gamme de S jusqu'à ici
}

Bien sûr, vous pouvez le faire correctement function_2.JPG

En parlant d'arguments de type, ce sont des génériques, n'est-ce pas?

Yamakasa <> ← C'est

Alors, en parlant de Yamakasa <> ...? Oui, c'est générique. Cette parenthèse <> est le même symbole à la place de la déclaration générique et à la place de l'appel générique (j'ose le dire), mais elle est utilisée dans un sens différent. C'est l'information pour montrer "les types utilisés dans les classes et les méthodes".

GenericsSsample.java


package example.java.generics;

public class GenericsSample {
    //ici "<>Déclare "Je recevrai le type avec ce nom d'argument"(Argument formel)
    public <T> void callGenerics(T value){
        System.out.println(value); //Quelle est la valeur de l'argument?
        System.out.println(value.getClass().getName()); //Quel est le type d'argument?
    } //Gamme de T jusqu'à ici
}

Main.java


package example.java.generics;

public class Main {
    public static void main(String[] args) {
        GenericsSample genericsSample = new GenericsSample();
        
        //ici "<>Déclare "J'exécuterai la méthode avec une valeur de ce type"(Argument réel)
        //ici  "()Déclare "La méthode sera exécutée avec la valeur de cet argument"(Argument réel)
        //Spécifiez simplement différents types d'arguments réels avec chaque symbole
        genericsSample.<Integer>callGenerics(1234);
    }
}

C'est la valeur et le type définis par l'argument correctement generics_3.JPG generics_8.JPG

Lorsque la valeur de type et le type de la valeur passée en argument (difficile à comprendre, ...) sont différents

Main.java


package example.java.generics;

public class Main {
    public static void main(String[] args) {
        GenericsSample genericsSample = new GenericsSample();
        genericsSample.<String>callGenerics(1234);
    }
}

Air dérangeant generics_6.JPG

Échouera en toute sécurité generics_7.JPG

Ecrire dans l'ordre de type → valeur

À Java en premier lieu

//Ordre des variables de type
String variable;

Puisqu'il est écrit dans "type-> order" comme, il est compréhensible que l'ordre des arguments représentant le type et la valeur soit aussi "generics-> value".

//Type → Valeur
//La raison pour laquelle le générique qui représente le type vient avant le void est que le type de retour peut être l'argument spécifié dans le générique(Dans ce cas "T")Parce qu'il y a(peut être)
public <T> void callGenerics(T value)

//Type → Valeur
genericsSample.<String>callGenerics(1234);

Génériques spécifiés pour la classe

Comme la méthode, la classe a juste une déclaration (argument formel) qui dit "J'accepterai le type avec ce nom d'argument".

GenericsSample.java


package example.java.generics;

//ici "<>Déclare "Je recevrai le type avec ce nom d'argument"(Argument formel)
public class GenericsSample<T> {

    //La portée de l'argument T du type spécifié dans la classe continue jusqu'à la méthode de la classe
    public void callGenerics(T value){
        System.out.println(value); //Quelle est la valeur de l'argument?
        System.out.println(value.getClass().getName()); //Quel est le type d'argument?
    }
} // <T>Gamme jusqu'à ici

Main.java


package example.java.generics;

public class Main {
    public static void main(String[] args) {
        //ici "<>Déclare "Je vais instancier une classe avec une valeur de ce type"(Argument réel)
        // new GenericsSample<Integer>Est nouveau générique<>Il est normal de l'omettre pour(GenericsSample<Integer>Pourquoi est-ce Integer? Déduit)
        GenericsSample<Integer> genericsSample = new GenericsSample<Integer>();

        //ici  "()Déclare "La méthode sera exécutée avec la valeur de cet argument"(Argument réel)
        genericsSample.callGenerics(1234);
    }
}

generics_15.JPG generics_9.JPG

Bien sûr, si vous spécifiez un type différent pour la méthode. .. ..

Main.java


package example.java.generics;

public class Main {
    public static void main(String[] args) {
        //ici "<>Déclare "Je vais instancier une classe avec une valeur de ce type"(Argument réel)
        // new GenericsSample<Integer>Est nouveau générique<>Il est normal de l'omettre pour(GenericsSample<Integer>Pourquoi est-ce Integer? Déduit)
        GenericsSample<Integer> genericsSample = new GenericsSample<Integer>();

        //ici  "()Déclare "La méthode sera exécutée avec la valeur de cet argument"(Argument réel)
        genericsSample.callGenerics("test");
    }
}

Air dérangeant generics_10.JPG

Échouera en toute sécurité generics_11.JPG

Si <> est attaché à la fois à la classe et à la méthode avec le même nom d'argument. ..

GenericsSample.java


package example.java.generics;

//ici "<>Déclare "Je recevrai le type avec ce nom d'argument"(Argument formel)
public class GenericsSample<T> {

    //ici "<>Déclare "Je recevrai le type avec ce nom d'argument"(Argument formel)
    //La portée de l'argument T du type spécifié dans la classe continue jusqu'à la méthode de la classe... ??
    public <T> void callGenerics(T value){
        System.out.println(value); //Quelle est la valeur de l'argument?
        System.out.println(value.getClass().getName()); //Quel est le type d'argument?
    }
} // <T>Gamme jusqu'à ici... ??

Main.java


package example.java.generics;

public class Main {
    public static void main(String[] args) {
        //ici "<>Déclare "Je vais instancier une classe avec une valeur de ce type"(Argument réel)
        // new GenericsSample<Integer>Est nouveau générique<>Il est normal de l'omettre pour(GenericsSample<Integer>Pourquoi est-ce Integer? Déduit)
        GenericsSample<Integer> genericsSample = new GenericsSample<Integer>();

        //ici  "()Déclare "La méthode sera exécutée avec la valeur de cet argument"(Argument réel)
        genericsSample.callGenerics("test");
    }
}

Pas du tout dérangeant generics_12.JPG generics_13.JPG

Je n'échouerai pas ... generics_14.JPG

La cause de ceci est ** où "<>" déclare "Je recevrai le type avec ce nom d'argument" (argument formel) **

Parce que je l'ai spécifié avec le même nom d'argument. Je l'ai écrasé avec une nouvelle variable de type local dans la méthode. C'est comme ↓.

GenericsSample.java


package example.java.generics;

//ici "<>Déclare "Je recevrai le type avec ce nom d'argument"(Argument formel)
public class GenericsSample<T> {

    //Dans la classe, l'argument réel des génériques spécifié au moment de l'instance de la classe(new GenericsSample<Integer>Entier)Est valable

    //La portée de l'argument T du type spécifié dans la classe est l'argument réel des génériques spécifiés au moment de la méthode(Cette fois, String)A été écrasé par
    // genericsSample.callGenerics("test");de"test"De ""test"Parce que c'est une chaîne<T>deTはStringだ!」と推論された)
    public <T> void callGenerics(T value){
        System.out.println(value); //Quelle est la valeur de l'argument?
        System.out.println(value.getClass().getName()); //Quel est le type d'argument?
    }
}

Ne peut-il pas être spécifié lors de la déclaration d'une classe statique?

**ne peux pas. ** ** Pour les classes non statiques

//ici "<>Déclare "Je vais instancier une classe avec une valeur de ce type"(Argument réel)
// new GenericsSample<Integer>Est nouveau générique<>Il est normal de l'omettre pour(GenericsSample<Integer>Pourquoi est-ce Integer? Déduit)

Mais quand c'est une classe statique, vous ne pouvez pas instancier la classe, non? C'est impossible car il n'y a pas de timing pour spécifier l'argument réel et le créer. .. (Mais s'il s'agit d'une unité de méthode statique, vous pouvez spécifier l'argument réel au moment de l'appel, vous pouvez donc spécifier l'argument de type des génériques!)

Conclusion

Ne paniquez pas car ce n'est qu'une dispute.

Recommended Posts

Comment penser quand on comprend soudainement les génériques
Comment remplacer des caractères que vous ne comprenez pas [Principe]
Réfléchissez à la façon de diviser MVC en M et V
Éléments à prendre en compte lors du choix de l'architecture d'un nouveau système
Comment penser la conception de classe (division) dans un système d'entreprise (1)
Comprendre en 5 minutes !! Comment utiliser Docker
À propos de "Injection de dépendances" et "Héritage" qui sont faciles à comprendre lorsqu'ils sont mémorisés ensemble
[Rails] Comment écrire lors de la création d'une sous-requête
Comprendre comment partager des connexions Spring DB (transactions DB)
Lorsque vous souhaitez lier InputStream dans JDBI3
Lorsque vous souhaitez utiliser la méthode à l'extérieur
Comment effacer la base de données lors de la recréation de l'application
Qu'utilisez-vous lors de la conversion en String?
[Ruby] Lorsque vous souhaitez remplacer plusieurs caractères
Comment supprimer le tweet associé à l'utilisateur lorsque vous le supprimez en même temps
Comment créer un plugin Vagrant que vous avez appris lorsque vous avez forké et publié vagrant-mutagen
Tu comprends vraiment? Comment vérifier la bibliothèque et la licence utilisées par l'application
Le point de vue lors de la révision du code d'une application web (Rails)
Résumé des points qui m'inquiétaient lors de la migration de Java vers Kotlin
Points à examiner lorsque Rubocop est lent à s'exécuter
À propos de la gestion des exceptions
À propos de la gestion des exceptions
Comment penser quand on comprend soudainement les génériques