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

Questo è un post tradotto da IA.

제이온

[Java] Concetto e utilizzo della Reflection

Seleziona la lingua

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

Testo riassunto dall'intelligenza artificiale durumis

  • La Reflection è un'API che consente di accedere alle informazioni di classe e di manipolare le classi in fase di runtime.
  • Tramite la Reflection, è possibile creare istanze di classe e accedere a campi e metodi indipendentemente dai modificatori di accesso e risulta particolarmente utile nella gestione dinamica delle dipendenze durante le fasi di sviluppo di grandi progetti, come nei framework.
  • Tuttavia, può violare l'incapsulamento e causare cali di prestazioni, quindi è meglio utilizzarla solo quando strettamente necessario.

Cos'è la Reflection?

La reflection è un'API che supporta la creazione di istanze di classi desiderate tramite oggetti di tipo Class caricati nell'area heap e supporta l'accesso ai campi e ai metodi delle istanze indipendentemente dai modificatori di accesso.



Qui, il termine classe caricata si riferisce alla creazione di un oggetto di tipoClassche contiene informazioni sulla classe corrispondente nella memoria heap dopo che il class loader JVM ha completato il caricamento del file di classe. Tieni presente che questo è diverso dagli oggetti creati tramite la parola chiave new. Se non capisci l'oggetto di tipo Class, dai un'occhiata alla documentazione JDK per l'oggetto java.lang.class.


Come usare

Prima di utilizzare la reflection, è necessario ottenere un oggetto di tipo Class caricato nell'area heap. Esistono 3 metodi.


  • Ottienilo con Class.class
  • Ottienilo con instance.getClass()
  • Ottienilo con Class.forName("nome_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("La password è 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("Jayon", 23, "Sviluppo Darath");
        Class memberClass2 = member.getClass();
        System.out.println(System.identityHashCode(memberClass2));

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

// Risultati dell'esecuzione
1740000325
1740000325

Puoi vedere che le istanze di tipo Class ottenute con i 3 metodi sono tutte uguali. Indipendentemente dal metodo utilizzato, il valore hash è lo stesso, quindi puoi usarlo in base alle tue esigenze.


Ora puoi creare istanze della classe corrispondente tramite il tipo Class ottenuto e accedere ai campi e ai metodi dell'istanza indipendentemente dai modificatori di accesso. Prima crea un'istanza della classe corrispondente.


public class Main {

    public static void main(String[] args) throws Exception {
        // Stampa tutti i costruttori di Member
        Member member = new Member();
        Class memberClass = member.getClass();
        Arrays.stream(memberClass.getConstructors()).forEach(System.out::println);

        // Creazione di un'istanza tramite il costruttore predefinito di Member
        Constructor constructor = memberClass.getConstructor();
        Member member2 = constructor.newInstance();
        System.out.println("member2 = " + member2);

        // Creazione di un'istanza tramite un altro costruttore di Member
        Constructor fullConstructor =
            memberClass.getConstructor(String.class, int.class, String.class);
        Member member3 = fullConstructor.newInstance("Jayon", 23, "Sviluppo Darath");
        System.out.println("member3 = " + member3);
    }
}

// Risultati dell'esecuzione
public Member()
public Member(java.lang.String,int,java.lang.String)
member2 = Member{name='null', age=0, hobby='null'}

Puoi ottenere il costruttore tramite getConstructor() e creare dinamicamente un'istanza di Member tramite newInstance().

Infine, accedi ai campi e ai metodi dell'istanza indipendentemente dai modificatori di accesso.

public class Main {

    public static void main(String[] args) throws Exception {
        Member member = new Member("Jayon", 23, "Sviluppo Darath");
        Class memberClass = member.getClass();

        // Accesso ai campi
        Field[] fields = memberClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            System.out.println(field.get(member));
        }
        fields[0].set(member, "Jayon2");
        System.out.println(member);

        // Accesso ai metodi
        Method speakMethod = memberClass.getDeclaredMethod("speak", String.class);
        speakMethod.invoke(member, "Test di Reflection");

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

// Risultati dell'esecuzione
Jayon
23
Sviluppo Darath
Member{name='Jayon2', age=23, hobby='Sviluppo Darath'}
Test di Reflection

Puoi ottenere tutte le variabili di istanza della classe tramite getDeclaredFileds() e ottenere il valore del campo tramite get() e modificare il valore del campo tramite set(). Tieni presente che quando accedi a un campo con un modificatore di accesso privato, devi impostare l'argomento di setAccessible() su true.


Puoi anche ottenere il metodo tramite getDeclaredMethod(). In questo caso, devi passare come argomenti il nome del metodo e il tipo di parametro. Allo stesso modo, quando accedi a un metodo con un modificatore di accesso privato, devi impostare l'argomento di setAccessible() su true. Infine, puoi chiamare il metodo ottenuto tramite l'API di reflection tramite invoke().


Pro e contro

  • Vantaggi
    • Ha la flessibilità di creare istanze di classi e accedere a campi e metodi indipendentemente dai modificatori di accesso in fase di esecuzione per eseguire le attività necessarie.
  • Svantaggi
    • Viola l'incapsulamento.
    • Poiché le istanze vengono create in fase di esecuzione, il tipo corrispondente non può essere verificato in fase di compilazione.
    • Poiché le istanze vengono create in fase di esecuzione, è difficile comprendere il flusso di lavoro specifico.
    • Le prestazioni sono più lente rispetto all'accesso diretto ai campi e ai metodi utilizzando la reflection. (Non è più lento in tutte le situazioni.)


Perché usarlo

Tramite l'API di reflection, puoi accedere alle informazioni sulla classe in fase di esecuzione e manipolare la classe a tuo piacimento. Puoi anche manipolare campi e metodi dichiarati con modificatori di accesso privati. Sembra una tecnologia che non dovrebbe essere utilizzata perché viola l'incapsulamento importante nella progettazione orientata agli oggetti.


In fase di sviluppo a livello di console di piccole dimensioni, lo sviluppatore può comprendere tutti gli oggetti e le dipendenze utilizzati nel programma in fase di compilazione. Tuttavia, nelle fasi di sviluppo di grandi dimensioni come i framework, è difficile comprendere numerosi oggetti e dipendenze. In questo caso, utilizzando la reflection, è possibile creare dinamicamente classi e stabilire dipendenze.


Ad esempio, guardando la Bean Factory di Spring, puoi vedere che se aggiungi un'annotazione come @Controller, @Service o @Repository, Bean Factory crea e gestisce automaticamente la classe a cui è stata aggiunta l'annotazione. Lo sviluppatore non ha mai comunicato a Bean Factory la classe corrispondente. Questo è possibile grazie alla reflection. Se viene trovata una classe a cui è stata aggiunta l'annotazione in fase di esecuzione, la reflection viene utilizzata per creare un'istanza della classe corrispondente, iniettare i campi necessari e salvarla nella Bean Factory.


Naturalmente, come detto sopra, poiché viola l'incapsulamento, è meglio usarlo solo quando necessario.


Fonte

제이온
제이온
제이온
제이온
[Effective Java] Item 1. Consider static factory methods instead of constructors I metodi di fabbrica statici sono un modo flessibile ed efficiente per creare istanze invece di costruttori. Possono avere un nome, restituire istanze che soddisfano determinate condizioni e migliorare le prestazioni tramite il caching. A differenza del m

27 aprile 2024

[Effettivi Java] Elemento 5. Non dichiarare risorse, utilizzare l'iniezione di dipendenze Se una classe dipende da risorse esterne, è meglio non utilizzare classi di utilità statiche o singleton. L'iniezione di dipendenze può migliorare la flessibilità, la riusabilità e la facilità di test della classe, e l'utilizzo del pattern di metodo di fa

28 aprile 2024

[Effective Java] Item 4. Utilizzare un costruttore privato per impedire l'istanziamento Per le classi di utilità che includono solo metodi e campi statici, è consigliabile impostare l'accesso al costruttore su privato per impedire l'istanziamento. Ciò impedisce agli utenti di creare istanze della classe in modo errato, in quanto si basano su

28 aprile 2024

[Javascript] Struttura dell'oggetto (V8) L'oggetto JavaScript in V8 Engine viene ottimizzato come una struttura in base allo stato e convertito in modalità Fast e modalità Dictionary che funziona come una hashmap. La modalità Fast è rapida con chiave e valore in un formato quasi fisso, ma se vie
곽경직
곽경직
곽경직
곽경직
곽경직

18 marzo 2024

[Non-major, sopravvivere come sviluppatore] 7. Cosa aiuta e cosa no quando si cerca un lavoro nel settore Quando ci si prepara a cercare lavoro come sviluppatore, il blog tecnologico è inefficiente, mentre GitHub è consigliato per la gestione dei progetti e la condivisione del codice sorgente. Tra le varie certificazioni, è consigliabile preparare l'esame per
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

29 marzo 2024

[Non specialisti, sopravvivere come sviluppatori] 14. Riepilogo dei contenuti del colloquio tecnico per sviluppatori junior Questa è una guida alla preparazione ai colloqui tecnici per sviluppatori junior. Copre argomenti come la memoria principale, le strutture dati, RDBMS e NoSQL, programmazione procedurale e orientata agli oggetti, override e overload, algoritmi di sostituz
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 aprile 2024

Modellazione concettuale dei dati La modellazione concettuale dei dati è il processo di separazione delle entità e di rappresentazione delle relazioni tra le entità tramite un ERD. Un'entità è un'unità di informazioni indipendente, mentre gli attributi sono i dati detenuti dall'entità. Gl
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그

8 aprile 2024

[React Hook] useState Questo articolo descrive in dettaglio il motivo per cui il gancio useState di React rirenderizza l'intero componente durante il rirendering, come mantenere i valori e la struttura di implementazione interna. L'analisi del codice ReactFiberHooks.js ti aiut
Sunrabbit
Sunrabbit
Sunrabbit
Sunrabbit

14 marzo 2024

[Non tecnico, sopravvivi come sviluppatore] 13. Colloquio tecnico per sviluppatori junior Presentiamo 7 domande frequenti durante i colloqui tecnici per sviluppatori junior e suggerimenti su come prepararsi al colloquio. Scopri le domande e le strategie di risposta in diversi settori come OOP, database, rete, algoritmi. Preparati per un colloq
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

1 aprile 2024