Java Reflection API-zelfstudie met voorbeeld

โšก Slimme samenvatting

Java De Reflection API analyseert en wijzigt de mogelijkheden van een klasse tijdens runtime, inclusief de velden, methoden en constructors. Deze handleiding legt het java.lang.reflect-pakket uit, de belangrijkste methoden van java.lang.Class en vier voorbeelden die de metadata van een klasse, variabele, methode en constructor uitlezen.

  • ๐Ÿ” Definitie: Reflectie inspecteert en wijzigt klassen en hun leden tijdens de uitvoering, zelfs privรฉklassen.
  • ???? Reflect-pakket: Veld-, methode-, constructor- en modifierklassen verzamelen declaratieve informatie over leden.
  • ???? ๏ธ Klassemethoden: getName(), getSuperclass(), getInterfaces() en getModifiers() retourneren kernklassemetadata.
  • ๐Ÿงช Uitgewerkte voorbeelden: Vier programma's extract metadata van een klasse, variabelen, methoden en constructors.
  • โš ๏ธ Voorzichtigheid: Reflection heeft toegang tot besloten leden en is trager, dus gebruik het alleen als laatste redmiddel.

Java Handleiding voor de Reflection API

Wat is reflectie in Java?

Java Reflectie is het proces waarbij alle mogelijkheden van een klasse tijdens de uitvoering worden geanalyseerd en aangepast. De Reflection API in Java wordt gebruikt om een โ€‹โ€‹klasse en haar leden, waaronder velden, methoden, constructors, enz., tijdens de uitvoering te manipuleren.

Een voordeel van de Reflection API in Java Het kan namelijk ook de individuele leden van de klas manipuleren.

Het pakket java.lang.reflect biedt veel klassen om reflectie te implementeren. De methoden van de klasse java.lang.Class worden gebruikt om de volledige metadata van een bepaalde klasse te verzamelen.

Klasse in java.lang.reflect-pakket

Hieronder volgt een lijst van divers Java klassen In het pakket java.lang.reflect implementeren we reflectie:

  • Veld: Deze klasse wordt gebruikt om declaratieve informatie te verzamelen, zoals het gegevenstype, de toegangsaanpasser, de naam en de waarde van een variabele.
  • Werkwijze: Deze klasse wordt gebruikt om declaratieve informatie te verzamelen, zoals de toegangsaanpasser, het retourtype, de naam, de parametertypen en het uitzonderingstype van een methode.
  • Constructeur: Deze klasse wordt gebruikt om declaratieve informatie te verzamelen, zoals de toegangsaanpasser, naam en parametertypen van een constructor.
  • Aanpasser: Deze klasse wordt gebruikt om informatie te verzamelen over een specifieke toegangsaanpasser.

Methoden gebruikt in java.lang.Class

  • public String getName(): Geeft de naam van de klasse terug.
  • public Class getSuperclass(): Retourneert de verwijzing naar de superklasse.
  • public Class[] getInterfaces(): Retourneert een array met interfaces die door de opgegeven klasse worden geรฏmplementeerd.
  • public int getModifiers(): Retourneert een integerwaarde die de modifiers van de opgegeven klasse vertegenwoordigt. Deze waarde moet als parameter worden doorgegeven aan de methode โ€œpublic static String toString(int i)โ€ die de toegangsspecificatie voor de gegeven klasse retourneert.

Hoe u volledige informatie over een klas kunt krijgen

Om informatie over te krijgen variabelenOm een โ€‹โ€‹object van een klasse te maken, moeten we de methoden en constructors van een klasse begrijpen. Het volgende voorbeeld laat verschillende manieren zien om een โ€‹โ€‹object van de klasse "Class" te creรซren:

Methoden gebruikt in java.lang.Class

public class Guru99ClassObjectCreation {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1 - By using Class.forName() method
        Class c1 = Class.forName("Guru99ClassObjectCreation");
        // 2 - By using getClass() method
        Guru99ClassObjectCreation guru99Obj = new Guru99ClassObjectCreation();
        Class c2 = guru99Obj.getClass();
        // 3 - By using .class
        Class c3 = Guru99ClassObjectCreation.class;
    }
}

Voorbeeld 1: Hoe krijg ik de metadata van een klasse?

Het volgende voorbeeld laat zien hoe je metadata zoals de klassenaam, de naam van de superklasse, de geรฏmplementeerde interfaces en de toegangsmodifiers van een klasse kunt verkrijgen.

We zullen de metadata van de onderstaande klasse verkrijgen. Guru99Base.class:

Metagegevens van klasse ophalen

import java.io.Serializable;
public abstract class Guru99Base implements Serializable, Cloneable {
}
  1. De naam van de klas is: Guru99Basis
  2. De toegangsmodifiers zijn: public en abstract
  3. Het heeft interfaces geรฏmplementeerd: serialiseerbaar en kloonbaar
  4. Omdat het geen enkele klasse expliciet heeft overgeรซrfd, is de superklasse: java.lang.Object

De onderstaande klasse zal de metadata ophalen van Guru99Base.class en print het:

Metagegevens van klasse ophalen

import java.lang.reflect.Modifier;
public class Guru99GetclassMetaData {
    public static void main(String[] args) throws ClassNotFoundException {
        // Create Class object for Guru99Base.class
        Class<Guru99Base> guru99ClassObj = Guru99Base.class;

        // Print name of the class
        System.out.println("Name of the class is : " + guru99ClassObj.getName());

        // Print super class name
        System.out.println("Name of the super class is : " + guru99ClassObj.getSuperclass().getName());

        // Get the list of implemented interfaces using getInterfaces() method
        Class[] guru99InterfaceList = guru99ClassObj.getInterfaces();

        // Print the implemented interfaces using a for-each loop
        System.out.print("Implemented interfaces are : ");
        for (Class guru99class1 : guru99InterfaceList) {
            System.out.print(guru99class1.getName() + " ");
        }
        System.out.println();

        // Get access modifiers using getModifiers() and Modifier.toString()
        int guru99AccessModifier = guru99ClassObj.getModifiers();
        System.out.println("Access modifiers of the class are : " + Modifier.toString(guru99AccessModifier));
    }
}
  1. Print de naam van de klasse met behulp van de getName()-methode.
  2. Print de naam van de superklasse met behulp van de getSuperclass().getName() methode.
  3. Print de namen van de geรฏmplementeerde interfaces.
  4. De toegangsmodifiers afdrukken die door de klasse worden gebruikt.

Metagegevens van klasse ophalen

Metagegevens van klasse ophalen

Voorbeeld 2: Hoe krijg ik de metadata van een variabele?

Het volgende voorbeeld laat zien hoe je de metadata van een variabele kunt opvragen.

Hier maken we een klasse aan met de naam Guru99VariableMetaData.class met enkele variabelen:

package guru;
public class Guru99VariableMetaData {
    public static int guru99IntVar1 = 1111;
    static int guru99IntVar2 = 2222;
    static String guru99StringVar1 = "guru99.com";
    static String guru99StringVar2 = "Learning Reflection API";
}

Stappen om de metagegevens over de variabelen in de bovenstaande klasse te verkrijgen:

  1. Maak een klasseobject van de bovenstaande klasse, d.w.z. Guru99VariableMetaData.class, zoals hieronder:
    Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
    Class guru99ClassObjVar = guru99ClassVar.getClass();
  2. Haal de metadata op in de vorm van een veldarray met behulp van de getFields() or getDeclaredFields() methoden zoals hieronder:
    Field[] guru99Field1 = guru99ClassObjVar.getFields();
    Field[] guru99Field2 = guru99ClassObjVar.getDeclaredFields();

De getFields() Deze methode retourneert de metadata van de openbare variabelen van de opgegeven klasse en van de superklasse daarvan.

De getDeclaredFields() Deze methode retourneert alleen de metadata van alle variabelen uit de opgegeven klasse.

  1. Haal de namen van de variabelen op met behulp van de methode โ€œpublic String getName()โ€.
  2. Bepaal het gegevenstype van de variabelen met behulp van de methode โ€œpublic Class getType()โ€.
  3. Haal de waarde van de variabele op met de methode โ€œpublic xxx get(Field)โ€. Hierbij kan xxx een byte, short of elk ander type waarde zijn dat we willen ophalen.
  4. Verkrijg de toegangsaanpassers van de variabelen met behulp van de methoden getModifiers() en Modifier.toString(int i).

Hier schrijven we een klasse om de metadata te verkrijgen van de variabelen die in de klasse aanwezig zijn. Guru99VariableMetaData.class:

Metagegevens van variabele ophalen

package guru;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Guru99VariableMetaDataTest {
    public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
        // Create Class object for Guru99VariableMetaData.class
        Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
        Class guru99ClassObjVar = guru99ClassVar.getClass();

        // Get the metadata of all the fields of the class
        Field[] guru99Field1 = guru99ClassObjVar.getDeclaredFields();

        // Print name, data types, access modifiers and values of the variables
        for (Field field : guru99Field1) {
            System.out.println("Variable name : " + field.getName());
            System.out.println("Datatype of the variable : " + field.getType());

            int guru99AccessModifiers = field.getModifiers();
            System.out.println("Access Modifiers of the variable : " + Modifier.toString(guru99AccessModifiers));
            System.out.println("Value of the variable : " + field.get(guru99ClassVar));
            System.out.println();
        }
    }
}
  1. Er is een klasseobject aangemaakt voor Guru99VariableMetaData.class.
  2. Alle metadata van de variabelen zijn opgeslagen in een veldarray.
  3. Alle variabelenamen in de klasse werden afgedrukt. Guru99VariableMetaData.class.
  4. Alle gegevenstypen van de variabelen in de klasse werden afgedrukt.
  5. Alle toegangsmodifiers van de variabelen in de klasse werden afgedrukt.
  6. De waarden van alle variabelen in de klasse werden afgedrukt.

Metagegevens van de methode ophalen

Metagegevens van de methode ophalen

Voorbeeld 3: Hoe krijg ik de metadata van een methode?

Het volgende voorbeeld laat zien hoe je de metadata van een methode kunt verkrijgen.

Hier maken we een klasse aan met de naam Guru99MethodMetaData.class met enkele methoden:

Metagegevens van de methode ophalen

package guru;
import java.sql.SQLException;
public class Guru99MethodMetaData {

    public void guru99Add(int firstElement, int secondElement, String result)
    throws ClassNotFoundException, ClassCastException {
        System.out.println("Demo method for Reflection API");
    }
    public String guru99Search(String searchString)
    throws ArithmeticException, InterruptedException {
        System.out.println("Demo method for Reflection API");
        return null;
    }
    public void guru99Delete(String deleteString)
    throws SQLException {
        System.out.println("Demo method for Reflection API");
    }
}

Stappen om de metadata over de methoden in de bovenstaande klasse te verkrijgen:

  1. Maak een klasseobject van de bovenstaande klasse, d.w.z. Guru99MethodMetaData.class, zoals hieronder:
    Guru99MethodMetaData guru99ClassVar = new Guru99MethodMetaData();
    Class guru99ClassObjVar = guru99ClassVar.getClass();
  2. Haal methode-informatie op uit een Method-array met behulp van de methoden getMethods() en getDeclaredMethods() zoals hieronder:
    Method[] guru99Method1 = guru99ClassObjVar.getMethods();
    Method[] guru99Method2 = guru99ClassObjVar.getDeclaredMethods();

    De getMethods() Deze methode retourneert de metadata van de openbare methoden van de opgegeven klasse en van de superklasse ervan. getDeclaredMethods() Deze methode retourneert alleen de metadata van alle methoden uit de opgegeven klasse.

  3. Haal de naam van de methode op met behulp van de getName () methode.
  4. Bepaal het retourtype van de methode met behulp van de getReturnType() methode.
  5. Verkrijg toegangsmodifiers van de methoden met behulp van de getModifiers() en Modifier.toString(int i) werkwijzen.
  6. Haal de parametertypen van de methode op met behulp van de getParameterTypes() methode die een array van klassen retourneert.
  7. Ontvang gegenereerde uitzonderingen met behulp van de getExceptionTypes() methode die een array van klassen retourneert.

Hier schrijven we een klasse om de metadata te verkrijgen van de methoden die in de klasse aanwezig zijn. Guru99MethodMetaData.class:

Metagegevens van de methode ophalen

package guru;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Guru99MethodMetaDataTest {

    public static void main(String[] args) {
        // Create Class object for Guru99MethodMetaData.class
        Class guru99ClassObj = Guru99MethodMetaData.class;

        // Get the metadata of all the methods using getDeclaredMethods()
        Method[] guru99Methods = guru99ClassObj.getDeclaredMethods();

        for (Method method : guru99Methods) {
            System.out.println("Name of the method : " + method.getName());
            System.out.println("Return type of the method : " + method.getReturnType());

            int guru99ModifierList = method.getModifiers();
            System.out.println("Method access modifiers : " + Modifier.toString(guru99ModifierList));

            Class[] guru99ParamList = method.getParameterTypes();
            System.out.print("Method parameter types : ");
            for (Class class1 : guru99ParamList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();

            Class[] guru99ExceptionList = method.getExceptionTypes();
            System.out.print("Exception thrown by method : ");
            for (Class class1 : guru99ExceptionList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();
        }
    }
}
  1. Er is een klasseobject aangemaakt voor Guru99MethodMetaData.class.
  2. Alle metadata van alle methoden zijn opgeslagen in een Method-array.
  3. Alle methodenamen die in de klasse voorkomen, werden afgedrukt.
  4. De retourtypen van de methoden in de klasse werden afgedrukt.
  5. Alle toegangsmodifiers van de methoden in de klasse werden afgedrukt.
  6. De parametertypen van de methoden werden afgedrukt.
  7. De uitzonderingen die door de methoden werden gegenereerd, werden afgedrukt.

Metagegevens van de methode ophalen

Metagegevens van de methode ophalen

Voorbeeld 4: Hoe krijg ik de metadata van constructors?

Het volgende voorbeeld laat zien hoe je de metadata van constructors kunt verkrijgen.

Hier maken we een klasse aan met de naam Guru99Constructor.class met verschillende constructors:

Metagegevens van constructeurs ophalen

package guru;

import java.rmi.RemoteException;
import java.sql.SQLException;

public class Guru99Constructor {

    public Guru99Constructor(int no) throws ClassCastException, ArithmeticException { }
    public Guru99Constructor(int no, String name) throws RemoteException, SQLException { }
    public Guru99Constructor(int no, String name, String address) throws InterruptedException { }
}

Hier schrijven we een klasse om de metadata van de constructors in de klasse te verkrijgen. Guru99Constructor.class:

Metagegevens van constructeurs ophalen

package guru;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class Guru99ConstructorMetaDataTest {

    public static void main(String[] args) {
        // Create Class object for Guru99Constructor.class
        Class guru99Class = Guru99Constructor.class;

        // Get all the constructor information in the Constructor array
        Constructor[] guru99ConstructorList = guru99Class.getConstructors();

        for (Constructor constructor : guru99ConstructorList) {
            System.out.println("Constructor name : " + constructor.getName());

            int guru99Modifiers = constructor.getModifiers();
            System.out.println("Constructor modifier : " + Modifier.toString(guru99Modifiers));

            Class[] guru99ParamList = constructor.getParameterTypes();
            System.out.print("Constructor parameter types : ");
            for (Class class1 : guru99ParamList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();

            Class[] guru99ExceptionList = constructor.getExceptionTypes();
            System.out.print("Exception thrown by constructors : ");
            for (Class class1 : guru99ExceptionList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();
        }
    }
}
  1. Er is een klasseobject aangemaakt voor Guru99Constructor.class.
  2. Alle metadata van alle constructors zijn verzameld in een constructor-array.
  3. Alle namen van de constructors die in de klasse aanwezig zijn, werden afgedrukt.
  4. Alle toegangsmodifiers van de constructors in de klasse zijn afgedrukt.
  5. De parametertypen van de constructors zijn afgedrukt.
  6. De uitzonderingen die door de constructors werden gegenereerd, werden afgedrukt.

Metagegevens van constructeurs ophalen

Metagegevens van constructeurs ophalen

Veelgestelde vragen

Reflectie maakt het mogelijk voor frameworks en AI-tools om klassen tijdens runtime te inspecteren en te instantiรซren. Het vormt de basis voor dependency injection, serialisatie en ORM-mapping.pingen het dynamisch laden van plugins zonder de exacte klassen tijdens het compileren te kennen.

AI kan snel reflectiecode genereren, maar je moet deze zorgvuldig controleren. Reflectie kan toegangscontroles omzeilen en beveiligings- en prestatierisico's met zich meebrengen, dus de gegenereerde code moet worden getest en gevalideerd.

Reflectie is trager dan directe methodeaanroepen, kan de inkapseling doorbreken door toegang te krijgen tot privรฉleden en kan beveiligings- en onderhoudsproblemen veroorzaken. Het moet alleen worden gebruikt als er geen eenvoudigere aanpak beschikbaar is.

Ja. Door `setAccessible(true)` te gebruiken, kan reflectie privรฉvelden lezen en wijzigen en privรฉmethoden aanroepen. Dit is krachtig voor testen en frameworks, maar kan de encapsulatie doorbreken en beveiligingsproblemen veroorzaken.

Vat dit bericht samen met: