Reflection API в Java - Часть 1

FacebooktwittertumblrFacebooktwittertumblr

Данная статья:

  • написана командой Vertex Academy. Надеемся, что она Вам будет полезна. Приятного прочтения!
  • это одна из статей из нашего "Самоучителя по Java" 
  • Данная статья предполагает, что Вы уже хорошо знаете ООП.

В этой статье мы узнаем, что такое Рефлексия (Reflection) в Java, зачем она нам нужна, каковы её минусы, а также научимся базовой работе с ней.

Для начала нам необходимо будет разобрать немного теории.

Что такое Рефлексия?

Рефлексия - это API, который позволяет:

  • получать информацию о переменных, методах внутри класса, о самом классе, его конструкторах, реализованных интерфейсах и т.д.;
  • получать новый экземпляр класса;
  • получать доступ ко всем переменным и методам, в том числе приватным;
  • преобразовывать классы одного типа в другой (cast);
  • делать все это во время исполнения программы (динамически, в Runtime).

Минусы Рефлексии

Как и у всего в этом мире, у Рефлексии есть свои недостатки:

  • Худшая производительность в сравнении с классической работой с классами, методами и переменными;
  • Ограничения безопасности. Если мы захотим использовать рефлексию на классе, который защищен с помощью специального класса SecurityManager, то ничего у не выйдет т.к. этот класс будет выбрасывать исключения каждый раз, как мы попытаемся получить доступ к закрытым членам класса. Такая защита может применяться, например, в Апплетах (Applets);
  • Получение доступа к внутренностям класса, что нарушает принцип инкапсуляции. Фактически, мы получаем доступ туда, куда обычному человеку лезть не желательно. Это как с розеткой, ребёнку лучше к ней не лезть, тогда как опытный электрик запросто с ней поладит.

Что такое Класс класса, у кого он есть?

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

Class есть у :

  • классов, интерфейсов, перечислений;
  • примитивов и обёрток над ними;
  • массивов;
  • void. Да, ключевое слово void также имеет Class.

В общем, Class есть у всех объектов в Java.


А теперь перейдем к практике, для этого нам понадобится класс Car

Как получить Класс класса?

Способ 1 - Сlass.forName(“имя.пакета.ИмяКласса”)

Вызов метода forName() необходимо обернуть в блок  try-catch т.к. метод может бросить ClassNotFoundException, в случае если он не найдет класс с таким именем.

Способ 2 - метод getClass() у экземпляра класса

В этом случае оборачивать метод getClass() в блок try-catch нет необходимости т.к. мы вызываем этот метод у существующего класса, который видит компилятор. Но, к сожалению, компилятор не может знать тип переменной до конца, поэтому мы и имеем "? extends Car", как дженерик тип.

Способ 3 - ИмяКласса.class

Здесь по той же причине не нужно использовать блок try-catch.

Если вы заметили, то чем больше мы знаем о классе, тем точнее будет тип класса при получении Класса класса.

В первом случае мы знаем только относительный путь к классу, это самый ненадёжный способ, поэтому и тип дженерика был Class<?>. Ведь тип будет известен только после того, как мы запустим программу, компилятор этого знать не может наперёд.

Во втором случае мы получили Класс класса прямиком из экземпляра класса. Такой способ надёжнее, но он является не самым оптимальным. В этом случае компилятор не знает, экземпляр этого класса перед нами или его наследник, поэтому он подставляет тип  Class<? extends Car>.

В третьем случае мы прямо указываем из какого класса мы хотим получить Класс. Тут нет возможности ошибится в имени, нет возможности получить класс наследника класса Car, как это было возможно во втором случае. Компилятор точно знает, что это за тип класса. Этот способ является самым надёжным, поэтому и тип здесь  Class<Car>.

Как получить информацию о переменных класса с помощью Рефлексии?

Получить информацию о переменных класса можно с помощью методов getDeclaredFields(),  getDeclaredField() и getFields(), getField().

Пример 1 getDeclaredFields()

Метод возвращает все объявленные переменные в классе

Вывод

Пример 2 getDeclaredField()

Метод возвращает переменную по её имени. Если переменной с таким именем нет, то метод выбросит checked NoSuchFieldException.

Вывод

Пример 3 getFields()

В отличии от метода getDeclaredFields(), метод getFields() возвращает только public переменные

Вывод

Пример 4 getField()

По аналогии с методом getFields(), метод getField() возвращает только public переменные. Даже если поле с таким именем есть, но оно не публичное, метод getField() бросит NoSuchFieldException

Вывод

Как получить информацию о методах в классе с помощью Рефлексии?

Получить информацию о методах класса можно с помощью методов getDeclaredMethods(), getDeclaredMethod(), getMethods(), getMethod() и getEnclosingMethod().

Пример 1 getDeclaredMethods()

Метод возвращает все объявленнные методы в классе

Вывод

Пример 2 getDeclaredMethod()

Метод getDeclaredMethod(String name, Class<?>... parameterTypes) принимает имя и var-args с типами параметров метода. Если такого метода в классе нет, мы получим checked NoSuchMethodException.

Вывод в консоль

Пример 3 getMethods()

Метод возвращает все public методы класса и public методы его родительского класса/интерфейсов

Вывод в консоль

Пример 4 getMethod()

Как и getMethods(), метод getMethod() возвращает только публичные методы. Если такого метода нет или он не публичный, мы получим NoSuchMethodException.

Вывод в консоль

Пример 5 getEnclosingMethod()

Если класс является локальным или анонимным, метод getEnclosingMethod() возвращает тот метод в котором этот класс был создан, иначе метод возвращает null.

Вывод в консоль:

На этом урок заканчивается

В этом уроке мы узнали:

  • что такое рефлексия;
  • каковы её минусы;
  • что такое класс класса;
  • как получить класс класса;
  • как получить информацию о переменных класса;
  • как получить информацию о методах класса.

Следующую статью "Reflection API в Java. Класс Field" читайте здесь.

Спасибо, что были с нами! 🙂


Надеемся, что наша статья была Вам полезна.  Можно записаться к нам на курсы по Java на сайте.

FacebooktwittertumblrFacebooktwittertumblr

FacebooktwittertumblrFacebooktwittertumblr
Самоучители--узнать детальнее--