Что такое Reflection и как его использовать?
Reflection, рефлексия – это средства манипуляции данными на основе знания о структуре классов этих данных, инструменты метапрограммирования.
Класс Class<T> используется как точка входа в мир рефлекшена. Его экземпляры предоставляют саму метаинформацию о содержимом класса и основные методы для работы с ним. Все классы относящиеся Java Reflection находятся в пакетах java.lang и java.lang.reflect .
Экземпляр класса Class можно получить тремя способами:
Литералом .class ;
Статическим фабричным методом Class.forName() ;
Методом getClass() экземпляров класса.
Использование Reflection API медленное и небезопасное. Оно позволяет ломать инвариантность состояний экземпляра, нарушать инкапсуляцию, и даже менять финальные поля.
Использовать рефлексию естественно в тестовом коде, в инструментах разработки, в фреймворках (особенно в связке с runtime-аннотациями). Рефлекшн в ординарном бизнес-коде обычно говорит о больших проблемах проектирования.
Нередко на интервью просят продемонстрировать пример использования рефлекшна. Один из самых близких для backend-разработчика примеров – инициализация классов-конфигураций в Spring Framework. Фреймворк с помощью рефлекшна сканирует внутренности таких классов. Поля и методы, помеченные специальными аннотациями, воспринимаются как объявления элементов экосистемы фреймворка.
Перевод "Reflection" на русский с транскрипцией и произношением
На каком-то уровне, оценки студента являются отражением уровня учителя.
On mature reflection we have decided to decline their offer.
По зрелом размышлении мы решили отказаться от их предложения.
She grimaced at her reflection in the mirror.
Она скорчила рожицу своему отражению в зеркале.
The article is a sober reflection on the state of our nation.
Статья представляет собой трезвые размышления о состоянии нашего народа / о положении в нашей стране.
The pulse is a reflection of the heart’s condition.
Пульс отражает состояние сердца.
She was looking at her reflection in the mirror.
Она смотрела на своё отражение в зеркале.
The lurid reflection of immense fires hung in the sky.
Пылающие отсветы бушующего огня отражались в небе.
He uttered not a word of reflection on his companion.
Он не высказал ни слова упрёка в адрес своего спутника.
Narcissus was a beautiful Greek youth who became enamored of his own reflection.
Нарцисс был красивым греческим юношей, который влюбился в своё собственное отражение.
The poem is a reflection on the passage of time.
Данное стихотворение является отражением течения времени.
Reflexion of sound is familiarly illustrated by the echo.
Отражение звука обычно иллюстрируется на примере такого явления как эхо.
She was studying her reflection in the mirror.
Она рассматривала свое отражение в зеркале.
A moment’s reflection will show the stupidity of this argument.
Стоит на минутку задуматься, и сразу же становится видна глупость этого аргумента.
His trousers had a sharp crease and you could see your reflection in his shoeshine.
Брюки его были отутюжены до острых складок, а обувь начищена до зеркального блеска.
He studied his reflection in the mirror.
Он вгляделся в своё отражение в зеркале.
This mirror is so grimy you can barely see your reflection in it.
Это зеркало такое грязное, что в нём еле-еле видно своё отражение.
Примеры, ожидающие перевода
His speech was an accurate reflection of the public mood.
Can you see your reflection in the glass?
Shirley saw her reflection in the shop window.
Для того чтобы добавить вариант перевода, кликните по иконке ☰ , напротив примера.
Что такое Reflection?
Reflection – это инструмент метапрограммирования, который даёт средства, с помощью которых можно манипулировать данными, зная структуру конкретного класса, к которым эта информация относятся.
Class<T> является входом в рефлексию. В экземплярах данного класса содержится информация о требуемом классе.
Имеющиеся способы получить Class:
· с помощью литерала .class;
· используя метод Class.forName();
· вызвав функцию getClass() для экземпляра.
Учтите, что применение Reflection является медленным и опасным. Его использование свидетельствует о значительных ошибках, допущенных на этапе проектирования приложения.
Обучающий бот с бесплатными тестами и практическими заданиями по Kotlin.
Курсовой проект – разработка Телеграм бота на Котлин для изучения иностранных слов. Включает: техническое задание, руководство по поэтапному написанию с код-ревью, работу с сетью и публикацию на сервере. И другие обучающие материалы в закрытом доступе.
Java Reflection API: методы и примеры использования
Рассказываем, что рефлексия Java и для чего она используется.

Содержание
Рассмотрим, что такое рефлексия в Java, какие возможности предоставляет API и как ее можно использовать в проектах. В статье приведем несколько примеров кода, которые можно запустить и посмотреть на результат, разберем схемы работы и особенности использования. Код проверенно работает с Java 11. Чтобы разобраться в методах рефлексии, потребуется практический опыт работы с Java.
Что такое Java Reflection API
Java Reflection — это особенный функционал, который позволяет программе получить доступ к приватным частям объектов или поменять поведение некоторых методов классов. Созданный таким образом код будет адаптироваться к входным данным и, например, не будет зависеть от типов, с которыми работает.
Это дает возможность писать код, который со временем будет эволюционировать, то есть не зависеть от текущих имплементаций методов или переменных. Главные преимущества рефлексии — свобода и адаптивность. При необходимости вызвать приватный метод класса можно не переписывать его, а вызвать через Java Reflection. Фактически рефлексия позволяет не следовать написанному коду, вводя новые правила. Можно пойти чуть дальше и начать перехватывать вызовы методов, подменяя их другой логикой, или создать программу, которая будет работать с еще не написанным классом.
Для чего используется рефлексия
Примеров, когда рефлексия становится полезной в проектах, множество. Рассмотрим несколько вариантов ее использования:
- При тестировании кода. Часто бывает нужно проверить корректность работы приватной функции, однако в тесте ее вызвать не получается именно из-за того, что она приватная. Вариантов решения задачи два — сделать ее на время публичной, а потом обратно приватной, или просто вызвать ее в тесте через рефлексию. Второй вариант намного проще и быстрее.
- При написании фреймворков и библиотек. В популярном Spring Framework рефлексия используется для создания бинов. Во время работы программы Spring Framework собирает данные о классах, помеченных аннотацией `@Component`, и создает для них экземпляры. Это позволяет создавать бины без явного указания их в конфигурационном файле.
- Для поиска и запуска тестов. Например, так применяет рефлексию библиотека JUnit. Опытные пользователи замечали, что тесты помечены аннотацией `@Test`. Это сделано как раз для того, чтобы во время работы JUnit прошелся по всем классам и запустил всё с этой аннотацией.
- Для сериализации и десериализации объектов. Например, библиотека Jackson использует рефлексию для сериализации и десериализации объектов в стандарте JSON. Без нее Jackson не смог бы прочитать значения приватных полей и корректно сохранить их в JSON-формате. То же касается и десериализации, когда Jackson должен восстановить значения всех полей, в том числе и приватных, — это было бы невозможно без рефлексии.
Больше узнать об этих библиотеках и научиться программировать поможет курс по Java онлайн-университета Skypro. Он включает 440 часов теории и практики, видеоуроки и вебинары с преподавателями — экспертами в области Java-разработки, а также мастер-классы с реальными рабочими задачами и поддержку наставников. После окончания курса студенты получают диплом о профессиональной переподготовке.
Особенности Java Reflection
Нужно понимать, что Java Reflection API — это часть языка, а не библиотеки. Это означает, что использовать рефлексию можно над любым классом, написанными на Java. Для этого достаточно импортировать пакет `java.lang.reflect` в свой код.
Стоит отметить, что рефлексия в Java является довольно медленной, поэтому ее стоит использовать при отсутствии других вариантов. Причина — большинство операций не определены до выполнения программы, что мешает оптимизации кода в ходе компиляции. Рефлексия использует динамическую загрузку классов, что также требует еще больше ресурсов.
Рефлексия в Java не поддерживается с примитивными типами данных, такими как, например, int. Чтобы использовать рефлексию с ними, придется создать классы-обертки вокруг них.
История рефлексии в Java
Само понятие рефлексии в Java было введено почти с самого начала существования этого языка программирования, в версии 1.1. До этого можно было работать только предопределенными классами.
В Java 1.1 появился класс `Class`. Именно он позволяет получить данные о классе, к которому принадлежит объект. Таким образом стало возможным узнать, какие методы существуют у класса, и вызвать их. Для этого не нужно инициировать `Class` с нужным классом.
Пример инициации класса `String` и получения всех методов `String`
С тех пор Java постоянно улучшала рефлексию, добавляя новые возможности. Например, в Java 5 появился новый оператор `instanceof`, который позволяет проверить, является ли объект экземпляром класса. А в Java 8 появился метод `getDeclaredMethods()`, который позволяет получить информацию о методах класса включая приватные.
Динамические прокси
Версия рефлексии в Java обладает еще одним очень полезным свойством — позволяет создавать динамические прокси. А они, в свою очередь, позволяют перехватывать вызовы к методам выбранного класса. Это может пригодиться, например, если нужно логировать вызовы к методам класса.
Примеры использования Java Reflection
Рассмотрим несколько имплементаций того, как можно использовать рефлексию в Java. Все примеры будут использовать класс `Human`, в котором есть приватное поле `name` и публичный геттер `getName()`, а также приватная функция `generateSecret()`. Приватная функция берет слово Secret и добавляет к нему входную строку, которую мы называем `salt`. Затем генерируется соответствующее строке число и выдается как результат.
Класс `Human` приведен ниже:
Получение метаданных класса
Ключевым для рефлексии является класс `Class`, именно он хранит всю информацию о классе, для которого был инициирован. Эти данные называют метаданными класса, то есть это вся доступная с помощью рефлексии информация о нем. Например, в метаданные входят имя класса, его модификаторы, родительский класс, интерфейсы, конструкторы, поля, методы и так далее.
В качестве примера создания класса Class для Human создадим класс `ReflectionExample` и в методе `main()` создадим объект класса `Human`. Для того чтобы получить соответствующий Class, достаточно вызвать функцию `getClass()` на любом объекте:
Теперь мы можем использовать переменную `humanClass` для того, чтобы получить конкретные данные о классе. Для этого можно вызвать следующие методы на объекте `humanClass`:
* `getName()` — возвращает имя и пакет класса;
* `getSimpleName()` — возвращает имя класса без пакета;
* `getModifiers()` — возвращает модификаторы класса;
* `getSuperclass()` — возвращает родительский класс;
* `getInterfaces()` — возвращает список интерфейсов, которые наследует класс;
* `getConstructors()` — возвращает список конструкторов класса;
* `getFields()` — возвращает список публичных полей класса;
* `getDeclaredFields()` — возвращает список всех полей класса, в том числе приватных;
* `getMethods()` — возвращает массив публичных методов класса;
* `getDeclaredMethods()` — возвращает массив всех методов класса, в том числе приватных;
* `getPackage()` — возвращает имя пакета класса.
В методах `getFields()` и `getMethods()` заключается основной функционал рефлексии. Именно они позволят нам в дальнейшем поменять приватные поля и вызвать приватные методы.
Получение метаданных переменной
Покажем, как получить доступ и поменять то, что хранится в приватной переменной `name` в классе `Human`, даже если у нее нет сеттера.
Так же, как и выше, создадим объект класса `Human` и соответствующий `Class`. Используем функцию `getDeclaredFields()` для получения всех, в том числе приватных полей класса. Далее пройдемся по массиву переменных и найдем ту, которую хотим поменять. Как только мы нашли переменную, можем сразу же поменять или прочитать ее значение. Для этого используем функцию `setAccessible()` для снятия ограничения доступа и `set()` для изменения или `get()` для чтения значения.
Если запустить этот код, можно увидеть, что имя изменилось на `Bob`, хотя изначально было `John`.
Получение метаданных метода
Теперь посмотрим, как получить метаданные обо всех методах класса, в том числе и приватных, а также вызвать любой из них. В Java Reflection методы можно получить сходным образом — это значит, что примеры получения метаданных метода и переменной во многом будут похожи.
Как и раньше, создадим объект класса `Human` и получим его метаданные. Далее используем `getDeclaredMethods` и получим список всех методов в этом классе. Среди этого списка найдем нужный и вызовем этот метод с собственными данными. Используем функцию `setAccessible()` для снятия ограничения доступа и `invoke()` непосредственно для вызова.
После запуска данной программы мы получим число из метода `getSecret`, несмотря на то что он был обозначен как приватный и нигде в коде класса не использовался.
Краткие итоги
Рефлексия в Java — многофункциональный и мощный инструмент. Он помогает программистам создавать различные фреймворки и библиотеки, позволяет писать гибкий код. Однако с рефлексией нужно работать с осторожностью, так как она может сильно замедлить работу программы.
