Структура данных Структура данных Java --- Отражение

Каталог статей

отражение

1. Определение отражения

Механизм отражения Java заключается в том, что в рабочем состоянии для любого класса можно знать все свойства и методы этого класса, для любого объекта можно вызывать любые его методы и свойства, так как вы можете его получить, мы можем модифицировать часть информации о типе; эта функция динамического получения информации и динамического вызова методов объекта называется механизмом отражения языка java.

2. Использование отражения

1. В ежедневном процессе разработки сторонних приложений часто встречается, что переменная-член, метод или свойство определенного класса являются закрытыми или открытыми только для системных приложений.В это время для передачи Reflection можно использовать механизм отражения Java. чтобы получить желаемый закрытый член или метод.

2. Наиболее важным применением рефлексии является разработка различных общих фреймворков.Например, в spring мы передаем все bean-компоненты классов в контейнер spring для управления, будь то bean-компоненты конфигурации XML или конфигурация аннотаций, когда мы получаем bean-компоненты из контейнер для внедрения зависимостей, контейнер будет считывать конфигурацию, а в конфигурации будет указана информация о классе.
На основе этой информации Spring должен создать эти bean-компоненты, а Spring создает эти классы динамически.

3. Отражайте основную информацию

Многие объекты в программах Java имеют два типа во время выполнения: тип времени выполнения (RTTI) и тип времени компиляции Например, Person p = new Student();в этом коде p имеет тип Person во время компиляции и тип студента во время выполнения.
Программам необходимо получать реальную информацию об объектах и ​​классах во время выполнения . Используя программу отражения, вы можете определить, к каким классам принадлежат объект и класс.

4. Классы, связанные с отражением

имя класса использовать
Сорт Объект, представляющий класс, представляющий классы и интерфейсы в работающем приложении Java.
Класс поля Представляет переменную-член класса/свойства класса
Класс метода метод класса
Класс конструктора Конструктор класса делегата

4.1 Класс класса

Объект, представляющий класс, представляющий классы и интерфейсы в работающем приложении Java.

После того, как файл Java скомпилирован, создается файл .class, и JVM будет интерпретировать .classфайл в это время.Скомпилированный файл Java .classтакже анализируется в объект JVM.Этот объект java.lang.Class. Таким образом, когда программа работает , каждый класс в конечном итоге изменится. Становится экземпляром объекта класса Class. Применяя механизм отражения Java к этому экземпляру, мы можем получить или даже добавить и изменить свойства и действия этого класса, сделав этот класс динамическим классом.

4.1.1 Связанные методы в классе Class

Обычно используемые методы для получения классов

метод использовать
получитькласслоадер() получить загрузчик классов
получитьобъявленные классы() Возвращает массив, содержащий объекты всех классов и классов интерфейса в этом классе (включая приватные)
forName (строковое имя класса) Возвращает объект класса на основе имени класса
новый экземпляр () Создайте экземпляр класса
получитьИмя() Получить полный путь к классу

Часто используемые методы для получения свойств, связанных с классами (возвращаемые значения следующих методов связаны с полем)

метод использовать
getField (имя строки) Получить объект публичной собственности
получить поля() Получить все объекты публичной собственности
getDeclaredField (имя строки) получить объект недвижимости
получитьобъявленные поля() получить все объекты недвижимости

Получить метод, связанный с аннотацией в классе

метод использовать
получить аннотацию (класс аннотации класса) Возвращает общедоступный объект аннотации в этом классе, который соответствует типу параметра.
получитьаннотации() Возвращает все общедоступные объекты аннотаций этого класса.
getDeclaredAnnotation (класс аннотаций класса) Возвращает все объекты аннотаций в этом классе, которые соответствуют типу параметра
получитьобъявленные аннотации() Возвращает все объекты аннотации этого класса

Получить в классе методы, связанные с конструктором (возвращаемые значения следующих методов связаны с конструктором)

метод использовать
getConstructor (Класс… <?> Типы параметров) Получить общедоступный конструктор в этом классе, который соответствует типу параметра
получитьконструкторы() Получить все общедоступные конструкторы этого класса
getDeclaredConstructor (Класс… <?> Типы параметров) Получите конструктор в этом классе, который соответствует типу параметра
получитьобъявленныеконструкторы() Получить все конструкторы этого класса

Получить метод, связанный с методом в классе (возвращаемое значение следующего метода связано с методом)

метод использовать
getMethod (имя строки, класс… <?> Типы параметров) Получить публичный метод этого класса
получитьметоды() Получить все общедоступные методы этого класса
getDeclaredMethod (имя строки, класс…<?> типы параметров) получить метод этого класса
получитьдекларедметодс() Получить все методы этого класса

4.2 Пример отражения

4.2.1 Три способа получения объектов класса

Перед отражением первый шаг, который нам нужно сделать, это сначала получить объект класса класса, который необходимо отразить, а затем использовать основной метод объекта класса для достижения цели отражения, то есть: в рабочем состоянии , для любого класса, все Мы можем знать все свойства и методы этого класса, для любого объекта мы можем вызывать любые его методы и свойства, Поскольку мы можем его получить, мы можем модифицировать некоторую информацию о типе.

第一种,使用 Class.forName(“类的全路径名”); 静态方法。
前提:已明确类的全路径名。

第二种,使用 .class 方法。
说明:仅适合在编译前就已经明确要操作的 Class

第三种,使用类对象的 getClass() 方法

class Student{
    
    
    //私有属性name
    private String name = "bit";
    //公有属性age
    public int age = 18;
    //不带参数的构造方法
    public Student(){
    
    
        System.out.println("Student()");
    }

    private Student(String name,int age) {
    
    
        this.name = name;
        this.age = age;
        System.out.println("Student(String,name)");
    }

    private void eat(){
    
    
        System.out.println("i am eat");
    }

    public void sleep(){
    
    
        System.out.println("i am pig");
    }

    private void function(String str) {
    
    
        System.out.println(str);
    }

    @Override
    public String toString() {
    
    
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Test {
    
    
    public static void main(String[] args) throws ClassNotFoundException {
    
    
        // 第一种,使用 Class.forName("类的全路径名"); 静态方法。
        Class<?> c1 = Class.forName("Student");

        // 第二种,使用 .class 方法。
        Class<?> c2 = Student.class;

        // 第三种,使用类对象的 getClass() 方法 (不常用)
        Student student = new Student();
        Class<?> c3 = student.getClass();

        System.out.println(c1 == c2); // true
        System.out.println(c1 == c3); // true
        System.out.println(c2 == c3); // true
    }
}

4.2.2 反射的使用

注意:所有和反射相关的包都在import java.lang.reflect包下面。

4.2.2.1 通过 Class 类的newInstance方法 获取 学生实例

/**
     * 通过 Class 类的newInstance方法 获取 学生实例
     */
    public static void reflectNewInstance() {
    
    
        try {
    
    
            Class<?> c1 = Class.forName("Student");

            Student student = (Student) c1.newInstance();
            System.out.println(student);
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (InstantiationException e) {
    
    
            e.printStackTrace();
        } catch (IllegalAccessException e) {
    
    
            e.printStackTrace();
        }
    }

在这里插入图片描述

4.2.2.2 反射所有的私有的构造方法

public static void reflectPrivateConstructor() {
    
    
        try {
    
    
            Class<?> c1 = Class.forName("Student");
            Constructor<?> constructor = c1.getDeclaredConstructor(String.class,int.class);//传的时候要 .class

            constructor.setAccessible(true); // 因为是私有的 所以要改为true

            Student student = (Student) constructor.newInstance("niubi",80);
            System.out.println(student);
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
    
    
            e.printStackTrace();
        } catch (InvocationTargetException e) {
    
    
            e.printStackTrace();
        } catch (InstantiationException e) {
    
    
            e.printStackTrace();
        } catch (IllegalAccessException e) {
    
    
            e.printStackTrace();
        }
    }

在这里插入图片描述

4.2.2.3 反射私有或者公开的属性

    public static void reflectPrivateField() {
    
    
        try {
    
    
            Class<?> c1 = Class.forName("Student");
            Student student = (Student) c1.newInstance();

            Field field = c1.getDeclaredField("name");
            field.setAccessible(true);

            field.set(student,"wang wu");
            System.out.println(student);
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (InstantiationException e) {
    
    
            e.printStackTrace();
        } catch (IllegalAccessException e) {
    
    
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
    
    
            e.printStackTrace();
        }
    }

在这里插入图片描述

4.2.2.4 反射私有方法

public static void reflectPrivateMethod() {
    
    
        try {
    
    
            Class<?> c1 = Class.forName("Student");
            Student student = (Student) c1.newInstance();

            Method method = c1.getDeclaredMethod("function", String.class);
            method.setAccessible(true);

            method.invoke(student,"牛逼 牛逼 牛逼 私有的方法");
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (InstantiationException e) {
    
    
            e.printStackTrace();
        } catch (IllegalAccessException e) {
    
    
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
    
    
            e.printStackTrace();
        } catch (InvocationTargetException e) {
    
    
            e.printStackTrace();
        }
    }

在这里插入图片描述

5. 反射优点和缺点

优点:

  1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法
  2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
  3. 反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等。

缺点:

  1. 使用反射会有效率问题。会导致程序效率降低。
  2. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂 。

Supongo que te gusta

Origin blog.csdn.net/wwzzzzzzzzzzzzz/article/details/123229323
Recomendado
Clasificación