Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

Ceci est un post traduit par IA.

제이온

[Java] Concept de réflexion et méthodes d'utilisation

Choisir la langue

  • Français
  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar

Texte résumé par l'IA durumis

  • La réflexion est une API qui permet d'accéder aux informations de classe au moment de l'exécution et de manipuler les classes comme vous le souhaitez.
  • La réflexion vous permet de créer des instances de classe et d'accéder aux champs et aux méthodes indépendamment des modificateurs d'accès. Elle est particulièrement utile pour gérer dynamiquement les dépendances dans les phases de développement à grande échelle, comme avec les frameworks.
  • Cependant, il est préférable de l'utiliser uniquement lorsque cela est nécessaire, car il peut violer l'encapsulation et entraîner des problèmes de performances.

Qu'est-ce que la réflexion ?

La réflexion est une API qui permet de créer des instances de classe souhaitées via des objets de type Class chargés dans la zone de tas et d'accéder aux champs et aux méthodes de l'instance indépendamment des modificateurs d'accès.



Ici, le terme "classes chargées" signifie que le chargeur de classes JVM a terminé le chargement du fichier de classe et a créé unobjet de type Classcontenant les informations de la classe, qui sont stockées dans la zone de tas en mémoire. Il faut noter que ce n'est pas la même chose que les objets créés à l'aide du mot-clé new. Si vous ne comprenez pas bien les objets de type Class, vous pouvez consulter la documentation JDK de java.lang.class.


Comment l'utiliser

Avant d'utiliser la réflexion, vous devez obtenir l'objet de type Class qui est chargé dans la zone de tas. Il existe trois méthodes pour ce faire.


  • Obtenez-le via Classe.class
  • Obtenez-le via Instance.getClass()
  • Obtenez-le via Class.forName("Nom de la classe")


public class Member {

    private String name;

    protected int age;

    public String hobby;

    public Member() {
    }

    public Member(String name, int age, String hobby) {
        this.name = name;
        this.age = age;
        this.hobby = hobby;
    }

    public void speak(String message) {
        System.out.println(message);
    }

    private void secret() {
        System.out.println("Le mot de passe est 1234.");
    }

    @Override
    public String toString() {
        return "Member{" +
            "name='" + name + '\'' +
            ", age=" + age +
            ", hobby='" + hobby + '\'' +
            '}';
    }
}

public class Main {

    public static void main(String[] args) throws ClassNotFoundException {
        Class memberClass = Member.class;
        System.out.println(System.identityHashCode(memberClass));

        Member member = new Member("Jayeon", 23, "Développement de Darath");
        Class memberClass2 = member.getClass();
        System.out.println(System.identityHashCode(memberClass2));

        Class memberClass3 = Class.forName("{Nom du paquet}.Member");
        System.out.println(System.identityHashCode(memberClass3));
    }
}

// Résultat de l'exécution
1740000325
1740000325

Vous pouvez voir que les trois instances de type Class obtenues par ces trois méthodes sont les mêmes. Quelle que soit la méthode utilisée, la valeur de hachage est la même, vous pouvez donc les utiliser en fonction des circonstances.


Maintenant, à partir de l'instance de type Class obtenue, vous pouvez créer des instances de cette classe et accéder aux champs et aux méthodes de l'instance indépendamment des modificateurs d'accès. Commençons par créer des instances de cette classe.


public class Main {

    public static void main(String[] args) throws Exception {
        // Affichage de tous les constructeurs de Member
        Member member = new Member();
        Class memberClass = member.getClass();
        Arrays.stream(memberClass.getConstructors()).forEach(System.out::println);

        // Création d'une instance via le constructeur par défaut de Member
        Constructor constructor = memberClass.getConstructor();
        Member member2 = constructor.newInstance();
        System.out.println("member2 = " + member2);

        // Création d'une instance via un autre constructeur de Member
        Constructor fullConstructor =
            memberClass.getConstructor(String.class, int.class, String.class);
        Member member3 = fullConstructor.newInstance("Jayeon", 23, "Développement de Darath");
        System.out.println("member3 = " + member3);
    }
}

// Résultat de l'exécution
public Member()
public Member(java.lang.String,int,java.lang.String)
member2 = Member{name='null', age=0, hobby='null'}

getConstructor() vous permet d'obtenir un constructeur et newInstance() vous permet de créer dynamiquement une instance de Member.

Enfin, accédons aux champs et aux méthodes de l'instance indépendamment des modificateurs d'accès.

public class Main {

    public static void main(String[] args) throws Exception {
        Member member = new Member("Jayeon", 23, "Développement de Darath");
        Class memberClass = member.getClass();

        // Accès au champ
        Field[] fields = memberClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            System.out.println(field.get(member));
        }
        fields[0].set(member, "Jayeon2");
        System.out.println(member);

        // Accès à la méthode
        Method speakMethod = memberClass.getDeclaredMethod("speak", String.class);
        speakMethod.invoke(member, "Test de réflexion");

        Method secretMethod = memberClass.getDeclaredMethod("secret");
        secretMethod.setAccessible(true);
        secretMethod.invoke(member);
    }
}

// Résultat de l'exécution
Jayeon
23
Développement de Darath
Member{name='Jayeon2', age=23, hobby='Développement de Darath'}
Test de réflexion

getDeclaredFileds() vous permet d'obtenir toutes les variables d'instance de la classe, get() vous permet d'obtenir la valeur du champ et set() vous permet de modifier la valeur du champ. Il faut noter qu'il faut passer true comme argument de setAccessible() pour accéder à un champ avec un modificateur d'accès private.


De même, getDeclaredMethod() vous permet d'obtenir une méthode. Vous devez passer le nom de la méthode et le type de paramètre comme arguments. De même, vous devez définir l'argument de setAccessible() sur true pour accéder à une méthode avec un modificateur d'accès private. Enfin, vous pouvez appeler la méthode obtenue via l'API de réflexion à l'aide de la méthode invoke().


Avantages et inconvénients

  • Avantages
    • L'API de réflexion offre une flexibilité, car elle permet de créer des instances de classe au moment de l'exécution et d'accéder aux champs et aux méthodes indépendamment des modificateurs d'accès, afin d'effectuer les tâches nécessaires.
  • Inconvénients
    • Elle viole l'encapsulation.
    • Les instances étant créées au moment de l'exécution, le type ne peut pas être vérifié au moment de la compilation.
    • Les instances étant créées au moment de l'exécution, il est difficile de comprendre le flux d'exécution précis.
    • L'accès via la réflexion est plus lent que l'accès direct aux champs et aux méthodes (mais ce n'est pas toujours le cas).


Raisons d'utilisation

L'API de réflexion vous permet d'accéder aux informations de classe au moment de l'exécution et de manipuler la classe à votre guise. Vous pouvez même manipuler les champs et les méthodes déclarés avec le modificateur d'accès private. Cela semble être une technique à éviter, car elle viole l'encapsulation, qui est un principe important de la conception orientée objet.


Dans un environnement de console de petite taille, le développeur peut facilement comprendre tous les objets et les dépendances utilisés dans le programme au moment de la compilation. Mais dans le cadre d'un développement de grande envergure comme les frameworks, il est difficile de comprendre un grand nombre d'objets et de dépendances. L'utilisation de la réflexion permet de créer dynamiquement des classes et d'établir des dépendances.


Par exemple, la fabrique de beans de Spring crée et gère les classes annotées avec @Controller, @Service, @Repository, etc., en attachant simplement ces annotations. Le développeur n'a pas informé la fabrique de beans de ces classes, mais cela est possible grâce à la réflexion. Si elle trouve une classe annotée au moment de l'exécution, elle utilise la réflexion pour créer une instance de cette classe, injecter les champs nécessaires et la stocker dans la fabrique de beans.


Bien sûr, il faut éviter de l'utiliser à moins que ce ne soit absolument nécessaire, car elle viole l'encapsulation, comme indiqué ci-dessus.


Sources

제이온
제이온
제이온
제이온
[Efficace Java] Item 1. Envisager des méthodes d'usine statiques à la place des constructeurs Les méthodes d'usine statiques sont un moyen flexible et efficace de créer des instances à la place des constructeurs. Elles peuvent avoir un nom, renvoyer des instances répondant à des conditions spécifiques et améliorer les performances grâce à la mise

27 avril 2024

[Effective Java] Item 4 : Utilisez un constructeur privé pour empêcher l'instanciation Pour les classes utilitaires qui ne contiennent que des méthodes et des champs statiques, il est préférable de définir l'accès du constructeur sur privé pour empêcher l'instanciation. Cela permet d'éviter que les utilisateurs ne confondent le constructeur

28 avril 2024

[Effective Java] Évitez la création d'objets inutiles Ce guide vous explique comment réduire la création d'objets inutiles en Java. Pour les objets immuables comme String et Boolean, il est préférable d'utiliser des littéraux. Il est également conseillé de mettre en cache les instances Pattern pour les expre

28 avril 2024

Modélisation de données conceptuelle La modélisation de données conceptuelle est le processus de séparation des entités et de représentation de leurs relations sous forme de diagramme ERD. Une entité est une unité d'information indépendante et un attribut est une donnée possédée par une enti
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그

8 avril 2024

[Javascript] Structure d'objet (V8) L'objet JavaScript dans le moteur V8 est optimisé comme une structure en fonction de l'état, passant du mode Fast, optimisé comme une structure, au mode Dictionary qui fonctionne comme une table de hachage. Le mode Fast est rapide lorsque les clés et les
곽경직
곽경직
곽경직
곽경직
곽경직

18 mars 2024

Comprendre les risques de l'investissement à effet de levier x3 Volatilité en baisse (volatility decay) Cet article de blogue documente la poursuite du rêve de devenir riche grâce à des investissements à effet de levier 3x, tout en réfléchissant aux possibilités de dégradation de la volatilité et d'échec de l'investissement, ainsi qu'aux efforts déployés po
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마

21 avril 2024

Créer une CLI élégante avec Rust Cet article explique comment implémenter une application CLI en Rust. Nous utiliserons les bibliothèques clap et ratatui pour créer un programme CLI avec des fonctionnalités de connexion et de déconnexion. Nous présentons les aspects clés du développement
곽경직
곽경직
곽경직
곽경직
곽경직

13 mars 2024

[Concurrency] Opération atomique : Clôture de mémoire et ordre de mémoire Ce billet de blog explique comment prendre en compte l'ordre de la mémoire dans les opérations atomiques et l'importance des options d'ordre. Il fournit une description des diverses options d'ordre, telles que Relaxed, Acquire, Release, AcqRel et SecCst,
곽경직
곽경직
곽경직
곽경직
곽경직

12 avril 2024

Mr. Know-All 5 – Février 2024 Les entreprises souhaitent intégrer des services d'IA LLM à leurs propres services afin d'offrir une meilleure expérience utilisateur et d'attirer de nouveaux clients. Dialogflow de Google est une solution qui offre une expérience utilisateur basée sur le
Pilot AISmrteasy
Pilot AISmrteasy
Pilot AISmrteasy
Pilot AISmrteasy

21 mars 2024