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

Это сообщение переведено AI.

제이온

[Java] Концепция отражения и способы использования

  • Язык написания: Корейский
  • Базовая страна: Все страны country-flag

Выбрать язык

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

Текст, резюмированный ИИ durumis

  • Отражение — это API, который позволяет получать доступ к информации о классах во время выполнения и манипулировать ими по своему усмотрению.
  • С помощью отражения можно создавать экземпляры классов и обращаться к полям и методам независимо от модификаторов доступа, что особенно полезно для динамического управления зависимостями на крупных этапах разработки, таких как фреймворки.
  • Однако следует использовать его только в случае необходимости, поскольку он может нарушать инкапсуляцию и снижать производительность.

Что такое Reflection?

Reflection — это API, который позволяет создавать экземпляры нужного класса с помощью объекта типа Class, загруженного в кучу,и предоставляющий доступ к полям и методам этого экземпляра независимо от модификаторов доступа.



Загруженный класс — это класс, который был полностью загружен загрузчиком классов JVM из файла класса,и информация о нем была сохранена в объекте типа Class,который хранится в куче. Обратите внимание, что этот объект отличается от объекта, созданного с помощью ключевого слова new. Если вы не знакомы с объектами типа Class, ознакомьтесь с документацией JDK по java.lang.class.


Как использовать

Прежде чем использовать Reflection, необходимо получить объект типа Class, загруженный в кучу. Существует три способа сделать это.


  • Получение объекта типа Class с помощью Class.class
  • Получение объекта типа Class с помощью instance.getClass()
  • Получение объекта типа Class с помощью Class.forName("имя класса")


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("Пароль — 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("Джейон", 23, "Разработка Dara");
        Class memberClass2 = member.getClass();
        System.out.println(System.identityHashCode(memberClass2));

        Class memberClass3 = Class.forName("{имя пакета}.Member");
        System.out.println(System.identityHashCode(memberClass3));
    }
}

// Результат выполнения
1740000325
1740000325

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


Теперь, когда мы получили объект типа Class, мы можем создавать экземпляры этого класса, а также получать доступ к его полям и методам независимо от модификаторов доступа. Сначала создадим экземпляр класса.


public class Main {

    public static void main(String[] args) throws Exception {
        // Вывод всех конструкторов Member
        Member member = new Member();
        Class memberClass = member.getClass();
        Arrays.stream(memberClass.getConstructors()).forEach(System.out::println);

        // Создание экземпляра с помощью конструктора по умолчанию Member
        Constructor constructor = memberClass.getConstructor();
        Member member2 = constructor.newInstance();
        System.out.println("member2 = " + member2);

        // Создание экземпляра с помощью другого конструктора Member
        Constructor fullConstructor =
            memberClass.getConstructor(String.class, int.class, String.class);
        Member member3 = fullConstructor.newInstance("Джейон", 23, "Разработка Dara");
        System.out.println("member3 = " + member3);
    }
}

// Результат выполнения
public Member()
public Member(java.lang.String,int,java.lang.String)
member2 = Member{name='null', age=0, hobby='null'}

С помощью getConstructor() можно получить конструктор и создать экземпляр Member с помощью newInstance().

Наконец, давайте получим доступ к полям и методам экземпляра, не обращая внимания на модификаторы доступа.

public class Main {

    public static void main(String[] args) throws Exception {
        Member member = new Member("Джейон", 23, "Разработка Dara");
        Class memberClass = member.getClass();

        // Доступ к полям
        Field[] fields = memberClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            System.out.println(field.get(member));
        }
        fields[0].set(member, "Джейон2");
        System.out.println(member);

        // Доступ к методам
        Method speakMethod = memberClass.getDeclaredMethod("speak", String.class);
        speakMethod.invoke(member, "Тест Reflection");

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

// Результат выполнения
Джейон
23
Разработка Dara
Member{name='Джейон2', age=23, hobby='Разработка Dara'}
Тест Reflection

С помощью getDeclaredFileds() можно получить все поля экземпляра класса, а с помощью get() — получить значение поля, а с помощью set() — изменить его. При этом обратите внимание, что при доступе к полям с модификатором private необходимо установить setAccessible() в true.


Методы можно получить с помощью getDeclaredMethod(). При этом необходимо передать в качестве аргументов имя метода и типы его параметров. Аналогично полям, при доступе к методам с модификатором private необходимо установить setAccessible() в true. Наконец, с помощью метода invoke() можно вызвать метод, полученный с помощью API Reflection.


Преимущества и недостатки

  • Преимущества
    • Reflection обеспечивает гибкость, позволяя создавать экземпляры классов во время выполнения, получать доступ к полям и методам независимо от модификаторов доступа, а также выполнять необходимые действия.
  • Недостатки
    • Нарушает инкапсуляцию.
    • Создает экземпляры во время выполнения, поэтому типы нельзя проверить во время компиляции.
    • Создает экземпляры во время выполнения, поэтому сложно отследить конкретный поток выполнения.
    • Reflection работает медленнее, чем обычный доступ к полям и методам. (Не всегда медленнее.)


Причины использования

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


В небольших консольных приложениях разработчик может легко определить все используемые объекты и зависимости во время компиляции. Однако в крупных проектах, таких как фреймворки, отследить огромное количество объектов и зависимостей может быть сложно. Reflection позволяет создавать и устанавливать зависимости классов динамически.


Например, в Bean Factory в Spring, если к классу прикреплены аннотации @Controller, @Service или @Repository, Bean Factory автоматически создает и управляет этими классами. Разработчик не сообщал Bean Factory об этих классах. Это возможно благодаря Reflection. Во время выполнения поиск идет по классам, к которым прикреплены эти аннотации, и если они найдены, Reflection создает экземпляр класса, вставляет необходимые поля и сохраняет его в Bean Factory.


Конечно, как упоминалось выше, инкапсуляция нарушается, поэтому Reflection стоит использовать только в крайнем случае.


Источники

제이온
제이온
제이온
제이온
[Эффективный Java] Пункт 2. Используйте билдер, если конструктор имеет много параметров При создании объектов с большим количеством параметров использование паттерна билдера может сделать код более чистым и удобочитаемым. Вы создаете объект билдера с обязательными параметрами, используете методы-сеттеры для установки необязательных параметро

27 апреля 2024 г.

[Эффективный Java] Элемент 4. Используйте частный конструктор, чтобы предотвратить создание экземпляра Для утилитарных классов, которые содержат только статические методы и поля, рекомендуется сделать конструктор частным, чтобы предотвратить создание экземпляра. Это предотвращает случайное создание экземпляра пользователем и делает наследование невозможным

28 апреля 2024 г.

[Эффективный Java] Пункт 5. Используйте инъекцию зависимостей, а не явно указывайте ресурсы Если класс зависит от внешних ресурсов, не используйте синглтоны и статические утилитарные классы. Инъекция зависимостей позволяет улучшить гибкость, повторное использование и тестируемость класса, а использование паттерна фабричного метода обеспечивает б

28 апреля 2024 г.

[Javascript] Структура объекта (V8) Объект JavaScript в движке V8 оптимизирован как структура данных в зависимости от состояния. Он может быть переключен в быстрый режим, как структура, или в режим словаря, как хэш-таблица. Быстрый режим быстрый, так как ключ и значение почти неизменны. Од
곽경직
곽경직
곽경직
곽경직
곽경직

18 марта 2024 г.

[Для неспециалистов, выживание как разработчик] 14. Краткое изложение часто задаваемых вопросов на техническом собеседовании для начинающих разработчиков Руководство по подготовке к техническому собеседованию для начинающих разработчиков. Объясняются концепции, которые часто встречаются на собеседованиях, такие как область основной памяти, структуры данных, RDBMS и NoSQL, процедурное и объектно-ориентирова
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 апреля 2024 г.

Концептуальное моделирование данных Концептуальное моделирование данных - это процесс разделения сущностей и представления отношений между ними в виде ERD. Сущность - это независимая единица информации, а атрибут - это данные, которыми обладает сущность. Идентификатор однозначно идентифицир
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그

8 апреля 2024 г.

Полный стек ИИ на основе открытого кода В экосистеме ИИ появляются все новые модели ИИ с открытым исходным кодом (LLM). Mistral, Llama, phi-2 и другие модели с мощными возможностями и открытыми лицензиями были опубликованы, а также разрабатываются различные инструменты для их использования. Lan
RevFactory
RevFactory
RevFactory
RevFactory

5 февраля 2024 г.

[Свидетельство о квалификации по металлообработке] Решение 33-го выпуска Информация о кристаллической структуре металлических материалов, процессе образования перлита, методах измерения размера зерна феррита, основных элементах стали и влиянии марганца, мерах по предотвращению закалочной хрупкости, характеристиках закалки, фор
blog.naver.com/gksmftordldi
blog.naver.com/gksmftordldi
blog.naver.com/gksmftordldi
blog.naver.com/gksmftordldi
blog.naver.com/gksmftordldi

23 апреля 2024 г.

Что такое JWT (JSON Web Token)? JSON Web Token (JWT) — это открытый стандарт для безопасной передачи информации, который использует подписанные токены для обеспечения целостности и безопасности информации. Заголовок содержит тип токена и алгоритм подписи, а полезная нагрузка — информаци
Seize the day
Seize the day
Seize the day
Seize the day
Seize the day

4 марта 2024 г.