Java Урок за API на Reflection с пример

⚡ Умно обобщение

Java Reflection API анализира и модифицира възможностите на клас по време на изпълнение, включително неговите полета, методи и конструктори. Този ресурс обяснява пакета java.lang.reflect, ключовите методи на java.lang.Class и четири примера, които четат метаданните на клас, променлива, метод и конструктор.

  • 🔍 Определение: Reflection проверява и променя класовете и техните членове по време на изпълнение, дори и частните.
  • 📦 Пакет „Отражение“: Класовете Field, Method, Constructor и Modifier събират декларативна информация за членовете.
  • ???? ️ Методи на класа: getName(), getSuperclass(), getInterfaces() и getModifiers() връщат метаданните на основния клас.
  • 🧪 Разработени примери: Четири програми, бившиtracметаданни на клас, променливи, методи и конструктори.
  • ⚠️ Внимание: Отражението може да осъществява достъп до частни членове и е по-бавно, така че го използвайте като последна мярка.

Java Урок за API за отражение

В какво е отражение Java?

Java Рефлексията е процес на анализ и модифициране на всички възможности на даден клас по време на изпълнение. API за рефлексия в Java се използва за манипулиране на клас и неговите членове, които включват полета, методи, конструктори и др., по време на изпълнение.

Едно от предимствата на Reflection API в Java е, че може да манипулира и частните членове на класа.

Пакетът java.lang.reflect предоставя много класове за имплементиране на рефлексия. Методите на класа java.lang.Class се използват за събиране на пълните метаданни на даден клас.

Клас в пакета java.lang.reflect

Следва списък на различни Java класове в пакета java.lang.reflect за имплементиране на отражение:

  • Невярно: Този клас се използва за събиране на декларативна информация, като например типа данни, модификатора за достъп, името и стойността на променлива.
  • Метод: Този клас се използва за събиране на декларативна информация, като например модификатор за достъп, тип на връщане, име, типове параметри и тип на изключение на метод.
  • конструктор: Този клас се използва за събиране на декларативна информация, като например модификатора за достъп, името и типовете параметри на конструктора.
  • Модификатор: Този клас се използва за събиране на информация за конкретен модификатор на достъп.

Методи, използвани в java.lang.Class

  • публичен низ getName(): Връща името на класа.
  • публичен клас getSuperclass(): Връща препратката към суперкласа.
  • публичен клас[] getInterfaces(): Връща масив от интерфейси, имплементирани от посочения клас.
  • публично цяло число getModifiers(): Връща цяло число, представляващо модификаторите на посочения клас, което трябва да се предаде като параметър на метода „public static String toString(int i)“, който връща спецификатора за достъп за дадения клас.

Как да получите пълна информация за даден клас

За да получите информация за променливи, методи и конструктори на даден клас, трябва да създадем обект на този клас. Следващият пример показва различни начини за създаване на обект от клас „Class“:

Методи, използвани в 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;
    }
}

Пример 1: Как да получите метаданни на клас

Следващият пример показва как да получите метаданни, като например името на класа, името на суперкласа, имплементираните интерфейси и модификаторите за достъп на клас.

Ще получим метаданните на класа по-долу с име Guru99Base.class:

Вземете метаданни на класа

import java.io.Serializable;
public abstract class Guru99Base implements Serializable, Cloneable {
}
  1. Името на класа е: Guru99База
  2. Модификаторите му за достъп са: public и abstract
  3. Има внедрени интерфейси: Serializable и Cloneable
  4. Тъй като не е разширил изрично нито един клас, неговият суперклас е: java.lang.Object

Класът по-долу ще получи метаданните на Guru99Base.class и го отпечатайте:

Вземете метаданни на класа

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. Изведете името на класа, използвайки метода getName().
  2. Изведете името на суперкласа, използвайки метода getSuperclass().getName().
  3. Изпишете имената на имплементираните интерфейси.
  4. Изведете модификаторите за достъп, използвани от класа.

Вземете метаданни на класа

Вземете метаданни на класа

Пример 2: Как да получите метаданни на променлива

Следният пример показва как да получите метаданните на променлива.

Тук създаваме клас с име Guru99VariableMetaData.class с някои променливи:

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";
}

Стъпки за получаване на метаданните за променливите в горния клас:

  1. Създайте обекта на класа на горния клас, т.е. Guru99VariableMetaData.class, както е показано по-долу:
    Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
    Class guru99ClassObjVar = guru99ClassVar.getClass();
  2. Получете метаданните под формата на масив от полета, използвайки getFields() or getDeclaredFields() методи като по-долу:
    Field[] guru99Field1 = guru99ClassObjVar.getFields();
    Field[] guru99Field2 = guru99ClassObjVar.getDeclaredFields();

- getFields() Методът връща метаданните на публичните променливи от посочения клас, както и от неговия суперклас.

- getDeclaredFields() Методът връща метаданните на всички променливи само от посочения клас.

  1. Получете името на променливите, използвайки метода „public String getName()“.
  2. Получете типа данни на променливите, използвайки метода „public Class getType()“.
  3. Получаваме стойността на променливата, използвайки метода „public xxx get(Field)“. Тук xxx може да бъде байт, short или всякакъв тип стойност, която искаме да извлечем.
  4. Получете модификаторите за достъп на променливите, използвайки методите getModifiers() и Modifier.toString(int i).

Тук пишем клас, за да получим метаданните на променливите, присъстващи в класа. Guru99VariableMetaData.class:

Вземете метаданни на променлива

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. Създаден е обект от клас за Guru99VariableMetaData.class.
  2. Получих всички метаданни на променливите в масив от полета.
  3. Отпечатани са всички имена на променливи в класа Guru99VariableMetaData.class.
  4. Отпечатани са всички типове данни на променливите в класа.
  5. Отпечатани са всички модификатори на достъпа на променливите в класа.
  6. Отпечатани са стойностите на всички променливи в класа.

Вземете метаданни на метода

Вземете метаданни на метода

Пример 3: Как да получите метаданни на метод

Следният пример показва как да получите метаданните на метод.

Тук създаваме клас с име Guru99MethodMetaData.class с някои методи:

Вземете метаданни на метода

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");
    }
}

Стъпки за получаване на метаданните за методите в горния клас:

  1. Създайте обекта на класа на горния клас, т.е. Guru99MethodMetaData.class, както е показано по-долу:
    Guru99MethodMetaData guru99ClassVar = new Guru99MethodMetaData();
    Class guru99ClassObjVar = guru99ClassVar.getClass();
  2. Получете информация за метода в масив от методи, използвайки методите getMethods() и getDeclaredMethods(), както е показано по-долу:
    Method[] guru99Method1 = guru99ClassObjVar.getMethods();
    Method[] guru99Method2 = guru99ClassObjVar.getDeclaredMethods();

    - getMethods() Методът връща метаданните на публичните методи от посочения клас, както и от неговия суперклас. getDeclaredMethods() Методът връща метаданните на всички методи само от посочения клас.

  3. Получете името на метода, използвайки getName () метод.
  4. Получете типа на връщаната стойност на метода, използвайки getReturnType() метод.
  5. Получете модификатори на достъпа на методите, използвайки getModifiers() намлява Modifier.toString(int i) методи.
  6. Получаване на типове параметри на метода с помощта на getParameterTypes() метод, който връща масив от клас.
  7. Получавайте хвърлени изключения, използвайки getExceptionTypes() метод, който връща масив от клас.

Тук пишем клас, за да получим метаданните на методите, присъстващи в класа. Guru99MethodMetaData.клас:

Вземете метаданни на метода

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. Създаден е обект от клас за Guru99MethodMetaData.class.
  2. Получихме всички метаданни на всички методи в масив от методи.
  3. Отпечатани са всички имена на методи, присъстващи в класа.
  4. Отпечатани са типовете връщания на методите в класа.
  5. Отпечатани са всички модификатори на достъпа на методите в класа.
  6. Отпечатани са типовете параметри на методите.
  7. Отпечатани са изключенията, генерирани от методите.

Вземете метаданни на метода

Вземете метаданни на метода

Пример 4: Как да получите метаданни на конструктори

Следващият пример показва как да се получат метаданните на конструкторите.

Тук създаваме клас с име Guru99Constructor.class с различни конструктори:

Вземете метаданни на конструктори

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 { }
}

Тук пишем клас, за да получим метаданните на конструкторите, присъстващи в класа. Guru99Конструктор.клас:

Вземете метаданни на конструктори

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. Създаден е обект от клас за Guru99Конструктор.клас.
  2. Получихме всички метаданни на всички конструктори в масив от конструктори.
  3. Отпечатани са имената на всички конструктори, присъстващи в класа.
  4. Отпечатани са всички модификатори за достъп на конструкторите в класа.
  5. Отпечатани са типовете параметри на конструкторите.
  6. Отпечатани са изключенията, генерирани от конструкторите.

Вземете метаданни на конструктори

Вземете метаданни на конструктори

Въпроси и Отговори

Рефлексията позволява на фреймворците и инструментите за изкуствен интелект да инспектират и създават инстанции на класове по време на изпълнение. Тя захранва инжектирането на зависимости, сериализацията, ORM картата.pingи динамично зареждане на плъгини без да се знаят точните класове по време на компилация.

Изкуственият интелект може бързо да изгради код за отражение, но трябва да го прегледате внимателно. Отражението може да заобиколи проверките за достъп и да въведе рискове за сигурността и производителността, така че генерираният код се нуждае от тестване и валидиране.

Отражението е по-бавно от директните извиквания на методи, може да наруши капсулирането чрез достъп до частни членове и може да причини проблеми със сигурността и поддръжката. Трябва да се използва само когато няма по-прост подход.

Да. Използвайки setAccessible(true), reflection може да чете и променя частни полета и да извиква частни методи. Това е мощно за тестване и рамки, но може да наруши капсулирането и да създаде проблеми със сигурността.

Обобщете тази публикация с: