Что такое рефлексия и почему она полезна?
Я особенно заинтересован в Java, но я предполагаю, что принципы одинаковы на любом языке.
java
reflection
terminology
Lehane
источник
источник
@Jailbreak
. Он обеспечивает прямой, безопасный с точки зрения типов доступ к частным полям, методам и т. Д. Позвольте компилятору Java безопасно проверить ваш код, а Manifold создаст для вас доступ к отражению. Узнайте больше: manifold.systems/docs.html#type-safe-reflectionОтветы:
Отражение имени используется для описания кода, который может проверять другой код в той же системе (или в самой себе).
Например, скажем, у вас есть объект неизвестного типа в Java, и вы хотели бы вызвать метод doSomething, если он существует. Система статической типизации Java на самом деле не предназначена для поддержки этого, если объект не соответствует известному интерфейсу, но используя отражение, ваш код может посмотреть на объект и выяснить, есть ли у него метод с именем doSomething, а затем вызвать его, если вы хочу.
Итак, чтобы дать вам пример кода этого на Java (представьте, что рассматриваемый объект - foo):
Одним из наиболее распространенных вариантов использования в Java является использование с аннотациями. JUnit 4, например, будет использовать отражение, чтобы просматривать ваши классы для методов, помеченных аннотацией @Test, и затем будет вызывать их при запуске модульного теста.
Есть несколько хороших примеров для размышления, с которых вы можете начать, по адресу http://docs.oracle.com/javase/tutorial/reflect/index.html.
И, наконец, да, концепции очень похожи в других статически типизированных языках, которые поддерживают рефлексию (например, C #). В динамически типизированных языках описанный выше вариант использования менее необходим (так как компилятор разрешит вызов любого метода для любого объекта, если во время выполнения произойдет сбой, если он не существует), но во втором случае поиска методов, которые отмечены или работа определенным образом все еще распространена.
Обновление из комментария:
источник
Method
,Constructor
,Modifier
,Field
,Member
, в основном , по- видимому все , кромеClass
) находятся в пределахjava.lang.*reflect*
пакета. Возможно, понятие «отражение» всесторонне включает как «самоанализ типа», так и модификацию во время выполнения?Например, все объекты в Java имеют метод
getClass()
, который позволяет вам определять класс объекта, даже если вы не знаете его во время компиляции (например, если вы объявили его какObject
) - это может показаться тривиальным, но такое отражение невозможно в менее динамичных языках, таких какC++
. Более расширенное использование позволяет перечислять и вызывать методы, конструкторы и т. Д.Отражение важно, поскольку оно позволяет вам писать программы, которым не нужно «знать» все во время компиляции, что делает их более динамичными, поскольку они могут быть связаны во время выполнения. Код может быть написан с использованием известных интерфейсов, но фактические классы, которые будут использоваться, могут быть созданы с использованием отражения из файлов конфигурации.
Именно по этой причине во многих современных рамках широко используются отражения. Большинство других современных языков также используют рефлексию, и в скриптовых языках (таких как Python) они еще более тесно интегрированы, так как это кажется более естественным в общей модели программирования этих языков.
источник
C++
действительно имеет информацию о типе времени выполнения. RTTIОдно из моих любимых применений отражения - метод дампа ниже. Он принимает любой объект в качестве параметра и использует API отражения Java для распечатки каждого имени поля и значения.
источник
callCount
должен быть установлен на ноль. Это значение используется для определения того, сколько вкладок должно предшествовать каждой строке вывода: каждый раз, когда дамп должен выводить «подобъект», выходные данные будут печататься как вложенные в родительский объект. Этот метод оказывается полезным, когда обернут в другой. ПосмотримprintDump(Object obj){ System.out.println(dump(obj, 0)); }
.Использование отражения
Отражение обычно используется программами, которым требуется возможность проверять или изменять поведение приложений, работающих на виртуальной машине Java, во время выполнения. Это относительно продвинутая функция и должна использоваться только разработчиками, которые хорошо разбираются в основах языка. С учетом этого предостережения рефлексия является мощной техникой и может позволить приложениям выполнять операции, которые в противном случае были бы невозможны.
Особенности расширяемости
Приложение может использовать внешние пользовательские классы, создавая экземпляры объектов расширяемости, используя их полностью определенные имена. Браузеры классов и среды визуальной разработки Браузер классов должен иметь возможность перечислять членов классов. Визуальные среды разработки могут выиграть от использования информации о типах, доступной в рефлексии, чтобы помочь разработчику в написании правильного кода. Отладчики и инструменты тестирования Отладчики должны иметь возможность проверять закрытые члены в классах. В тестовых системах можно использовать отражение, чтобы систематически вызывать API-интерфейсы обнаруживаемого набора, определенные в классе, для обеспечения высокого уровня покрытия кода в тестовом наборе.
Недостатки отражения
Отражение мощно, но не должно использоваться без разбора. Если возможно выполнить операцию без использования отражения, то предпочтительно избегать ее использования. При обращении к коду с помощью рефлексии следует учитывать следующие проблемы.
Поскольку отражение включает в себя типы, которые разрешаются динамически, некоторые оптимизации виртуальных машин Java не могут быть выполнены. Следовательно, отражающие операции имеют более низкую производительность, чем их неотражающие аналоги, и их следует избегать в разделах кода, которые часто вызываются в чувствительных к производительности приложениях.
Отражение требует разрешения времени выполнения, которое может отсутствовать при работе под менеджером безопасности. Это важно для кода, который должен выполняться в ограниченном контексте безопасности, например в апплете.
Поскольку рефлексия позволяет коду выполнять операции, которые были бы недопустимыми в неотражающем коде, такие как доступ к закрытым полям и методам, использование рефлексии может привести к неожиданным побочным эффектам, которые могут сделать код неработоспособным и разрушить переносимость. Рефлексивный код нарушает абстракции и, следовательно, может изменить поведение при обновлении платформы.
источник: Reflection API
источник
Reflection - это ключевой механизм, позволяющий приложению или фреймворку работать с кодом, который еще не был написан!
Возьмем, к примеру, ваш типичный файл web.xml. Он будет содержать список элементов сервлета, которые содержат вложенные элементы класса сервлета. Контейнер сервлета обработает файл web.xml и создаст новый новый экземпляр каждого класса сервлета с помощью отражения.
Другим примером может быть Java API для синтаксического анализа XML (JAXP) . Когда поставщик синтаксического анализатора XML подключается через общеизвестные системные свойства, которые используются для конструирования новых экземпляров посредством отражения.
И, наконец, наиболее полный пример - это Spring, который использует отражение для создания своих компонентов и для интенсивного использования прокси.
источник
Не каждый язык поддерживает рефлексию, но принципы обычно одинаковы в языках, которые его поддерживают.
Отражение - это способность «размышлять» о структуре вашей программы. Или более конкретно. Чтобы взглянуть на имеющиеся у вас объекты и классы и программно получить информацию о методах, полях и интерфейсах, которые они реализуют. Вы также можете посмотреть на такие вещи, как аннотации.
Это полезно во многих ситуациях. Везде, где вы хотите иметь возможность динамически подключать классы в ваш код. Многие реляционные картографы объектов используют отражение, чтобы иметь возможность создавать объекты из баз данных, не зная заранее, какие объекты они собираются использовать. Плагин архитектуры является еще одним местом, где отражение полезно. В таких ситуациях важно иметь возможность динамически загружать код и определять, есть ли там типы, которые реализуют правильный интерфейс для использования в качестве плагина.
источник
Reflection позволяет создавать экземпляры новых объектов, вызывать методы и операции get / set с переменными класса динамически во время выполнения, не имея предварительных знаний о его реализации.
В приведенном выше примере нулевой параметр - это объект, для которого вы хотите вызвать метод. Если метод статический, вы вводите ноль. Если метод не является статическим, то при вызове вам нужно предоставить действительный экземпляр MyObject вместо null.
Отражение также позволяет вам получить доступ к закрытому члену / методам класса:
,
java.lang.reflect
). Метаданные класса могут быть доступны черезjava.lang.Class
.Reflection - очень мощный API, но он может замедлить работу приложения, если используется в избытке, так как он разрешает все типы во время выполнения.
источник
Java Reflection довольно мощный и может быть очень полезным. Java Reflection позволяет проверять классы, интерфейсы, поля и методы во время выполнения, не зная имен классов, методов и т. Д. Во время компиляции. Также возможно создавать новые объекты, вызывать методы и получать / устанавливать значения полей, используя отражение.
Быстрый пример Java Reflection, чтобы показать вам, как выглядит отражение:
Этот пример получает объект Class из класса MyObject. Используя объект класса, пример получает список методов этого класса, выполняет итерацию методов и выводит их имена.
Как именно все это работает, объясняется здесь
Изменить : После почти 1 года я редактирую этот ответ, так как во время чтения об отражении я получил еще несколько вариантов использования Отражения.
Когда контекст Spring обрабатывает этот элемент <bean>, он будет использовать Class.forName (String) с аргументом "com.example.Foo" для создания экземпляра этого класса.
Затем он снова будет использовать отражение, чтобы получить соответствующий установщик для элемента <property> и установить его значение в указанное значение.
Для частных методов,
Для частных полей
источник
Пример:
Возьмем, к примеру, удаленное приложение, которое дает вашему приложению объект, который вы получаете с помощью их методов API. Теперь, основываясь на объекте, вам может потребоваться выполнить какое-то вычисление.
Поставщик гарантирует, что объект может быть 3-х типов, и нам нужно выполнять вычисления в зависимости от типа объекта.
Таким образом, мы можем реализовать в 3 классах, каждый из которых содержит различную логику. Очевидно, что информация об объекте доступна во время выполнения, поэтому вы не можете статически кодировать для выполнения вычислений, следовательно, отражение используется для создания экземпляра объекта класса, который вам требуется для выполнения вычислений на основе объект получен от провайдера.
источник
instanceof
для определения типа объекта во время выполнения?Простой пример для размышления. В шахматной игре вы не знаете, что будет перемещено пользователем во время выполнения. Отражение можно использовать для вызова методов, которые уже реализованы во время выполнения:
источник
Reflection - это API, который используется для проверки или изменения поведения методов, классов, интерфейсов во время выполнения.
java.lang.reflect package
.java.lang
Иjava.lang.reflect
пакеты обеспечивают классы для Java Reflection.Отражение может быть использовано для получения информации о -
Класс
getClass()
метод используется , чтобы получить имя класса , к которому принадлежит объект.Конструкторы
getConstructors()
метод используется для получения государственных конструкторов класса , к которому принадлежит объект.Методы
getMethods()
метод используется для получения общих методов класса , к которой принадлежит объекты.Reflection API используется в основном:
IDE (интегрированная среда разработки), например Eclipse, MyEclipse, NetBeans
и т. Д. Средства отладки и тестирования и т. Д.
Преимущества использования отражения:
Функции расширяемости. Приложение может использовать внешние пользовательские классы, создавая экземпляры объектов расширяемости, используя их полностью определенные имена.
Инструменты отладки и тестирования. Отладчики используют свойство отражения для проверки закрытых членов классов.
Недостатки:
Повышение производительности: отражающие операции имеют более низкую производительность, чем их неотражающие аналоги, и их следует избегать в тех разделах кода, которые часто вызываются в чувствительных к производительности приложениях.
Воздействие внутренних элементов: рефлексивный код нарушает абстракции и, следовательно, может изменить поведение при обновлении платформы.
Ссылка: Java Отражение javarevisited.blogspot.in
источник
Согласно моему пониманию:
Отражение позволяет программисту динамически получать доступ к объектам в программе. т.е. при кодировании приложения, если программист не знает о классе или его методах, он может использовать этот класс динамически (во время выполнения) с помощью отражения.
Это часто используется в сценариях, где имя класса часто меняется. Если возникает такая ситуация, то программисту сложно переписать приложение и снова и снова менять имя класса.
Вместо этого, используя рефлексию, нужно беспокоиться о возможном изменении имени класса.
источник
Отражение - это набор функций, который позволяет вам получить доступ к информации о времени выполнения вашей программы и изменить ее поведение (с некоторыми ограничениями).
Это полезно, поскольку позволяет изменять поведение во время выполнения в зависимости от метаинформации вашей программы, то есть вы можете проверить тип возвращаемого значения функции и изменить способ обработки ситуации.
Например, в C # вы можете загрузить сборку (.dll) во время выполнения, исследовать ее, перемещаться по классам и выполнять действия в соответствии с тем, что вы нашли. Он также позволяет создавать экземпляр класса во время выполнения, вызывать его метод и т. Д.
Где это может быть полезно? Не полезно каждый раз, но для конкретных ситуаций. Например, вы можете использовать его, чтобы получить имя класса для целей ведения журнала, чтобы динамически создавать обработчики для событий в соответствии с тем, что указано в файле конфигурации, и так далее ...
источник
Я просто хочу добавить некоторые моменты ко всему, что было перечислено.
С помощью Reflection API вы можете написать универсальный
toString()
метод для любого объекта.Это полезно при отладке.
Вот несколько примеров:
источник
Отражение - позволить объекту увидеть их внешний вид. Этот аргумент, похоже, не имеет ничего общего с рефлексией. На самом деле, это способность «самоидентифицироваться».
Отражение само по себе является словом для таких языков, которые не обладают способностью к самопознанию и самочувствию, как Java и C #. Поскольку у них нет способности к самопознанию, когда мы хотим наблюдать, как это выглядит, у нас должна быть другая вещь, чтобы подумать о том, как это выглядит. Отличные динамические языки, такие как Ruby и Python, могут воспринимать свое отражение без помощи других людей. Можно сказать, что объект Java не может воспринимать, как он выглядит без зеркала, которое является объектом класса отражения, но объект в Python может воспринимать его без зеркала. Вот почему нам нужно отражение в Java.
источник
Со страницы документации Java
AccessibleObject
позволяет подавить проверки доступа, если необходимоReflectPermission
.Классы в этом пакете, наряду с
java.lang.Class
приложениями, такими как отладчики, интерпретаторы, инспекторы объектов, браузеры классов и сервисы, такие какObject Serialization
иJavaBeans
которым требуется доступ либо к открытым членам целевого объекта (на основе его класса времени выполнения), либо к членам, объявленным данный классВключает в себя следующие функции.
Посмотрите на эту ссылку документации для методов, представленных
Class
классом.Из этой статьи (Деннис Сосноски, президент Sosnoski Software Solutions, Inc) и этой статьи (pdf-исследования безопасности):
Я вижу значительные недостатки, чем использование отражения
Пользователь Reflection:
Недостатки отражения:
Общие нарушения:
Посмотрите на этот вопрос SE, касающийся злоупотребления функцией отражения:
Как мне прочитать приватное поле в Java?
Резюме:
Небезопасное использование его функций из системного кода также может легко привести к компрометации режима безопасности Java l. Так что используйте эту функцию экономно
источник
Woozle
проверял другие классы при запуске, чтобы увидеть, какие из них имеют статическийRegisterAsWoozleHelper()
метод, и вызывал все такие методы, которые он находит, с помощью обратного вызова, который они могут использовать, чтобы рассказатьWoozle
о себе, избегая необходимо использовать отражение при десериализации данных.Как предполагает само имя, оно отражает то, что оно содержит, например, метод класса и т. Д., Помимо предоставления возможности динамического вызова экземпляра метода, создающего экземпляр во время выполнения.
Он используется многими фреймворками и приложениями под лесом для вызова сервисов, фактически не зная кода.
источник
Reflection дает вам возможность писать более общий код. Это позволяет вам создавать объект во время выполнения и вызывать его метод во время выполнения. Следовательно, программа может быть сделана высоко параметризованной. Это также позволяет исследовать объект и класс, чтобы обнаружить его переменные и метод, выставленный внешнему миру.
источник
Reflection
имеет много применений . Тот, с которым я больше знаком, - это возможность создавать код на лету.источник
Я хочу ответить на этот вопрос примером. Прежде всего,
Hibernate
проект используетReflection API
генерациюCRUD
операторов для преодоления пропасти между запущенным приложением и хранилищем сохраняемости. Когда все меняется в домене,Hibernate
они должны знать о них, чтобы сохранить их в хранилище данных и наоборот.Альтернативно работает
Lombok Project
. Он просто внедряет код во время компиляции, в результате код вставляется в классы вашего домена. (Я думаю, что это нормально для добытчиков и сеттеров)Hibernate
выбралreflection
потому что это оказывает минимальное влияние на процесс сборки приложения.А из Java 7 мы имеем
MethodHandles
, который работает какReflection API
. В проектах для работы с регистраторами мы просто копируем и вставляем следующий код:Потому что в этом случае сложно сделать опечатку.
источник
Как мне кажется, лучше объяснить на примере, и ни один из ответов, похоже, не делает этого ...
Практическим примером использования отражений может быть языковой сервер Java, написанный на Java, или языковой сервер PHP, написанный на PHP, и т. Д. Language Server предоставляет вашим IDE такие возможности, как автозаполнение, переход к определению, контекстная помощь, типы подсказок и многое другое. Чтобы все имена тегов (слова, которые могут быть автоматически заполнены) отображать все возможные совпадения при вводе, языковой сервер должен проверять все, что касается класса, включая блоки документов и закрытые члены. Для этого нужно отражение указанного класса.
Другим примером будет юнит-тест частного метода. Один из способов сделать это - создать отражение и изменить область действия метода на public на этапе настройки теста. Конечно, можно утверждать, что частные методы не следует тестировать напрямую, но это не главное.
источник