Вопрос-ответ

What is reflection and why is it useful?

Что такое отражение и почему оно полезно?

Что такое отражение и почему оно полезно?

Меня особенно интересует Java, но я предполагаю, что принципы одинаковы в любом языке.

Переведено автоматически
Ответ 1

Название отражение используется для описания кода, который способен проверять другой код в той же системе (или сам себя).

Допустим, у вас есть объект неизвестного типа в Java, и вы хотели бы вызвать для него метод 'doSomething', если таковой существует. Система статической типизации Java на самом деле не предназначена для поддержки этого, если только объект не соответствует известному интерфейсу, но используя отражение, ваш код может посмотреть на объект и выяснить, есть ли у него метод с именем 'doSomething', а затем вызвать его, если вы хотите.

Итак, чтобы дать вам пример кода этого на Java (представьте, что рассматриваемый объект - foo ) :

Method method = foo.getClass().getMethod("doSomething", null);
method.invoke(foo, null);

Одним из очень распространенных вариантов использования Java является использование с аннотациями. JUnit 4, например, будет использовать отражение для поиска в ваших классах методов, помеченных аннотацией @Test , и затем будет вызывать их при запуске модульного теста.

Для начала приведем несколько хороших примеров отражения http://docs.oracle.com/javase/tutorial/reflect/index.html

И, наконец, да, концепции во многом схожи в других статически типизированных языках, которые поддерживают отражение (например, C #). В языках с динамической типизацией описанный выше вариант использования менее необходим (поскольку компилятор разрешает вызывать любой метод для любого объекта, завершаясь сбоем во время выполнения, если он не существует), но второй случай поиска методов, которые помечены или работают определенным образом, по-прежнему распространен.

Обновление из комментария:


Возможность проверять код в системе и видеть типы объектов - это не отражение, а скорее самоанализ типа. Таким образом, отражение - это возможность вносить изменения во время выполнения с использованием самоанализа. Здесь необходимо провести различие, поскольку некоторые языки поддерживают самоанализ, но не рефлексию. Одним из таких примеров является C ++


Ответ 2

Отражение - это способность языка проверять и динамически вызывать классы, методы, атрибуты и т.д. во время выполнения.


Например, все объекты в Java имеют метод getClass(), который позволяет вам определить класс объекта, даже если вы не знаете его во время компиляции (например, если вы объявили его как Object) - это может показаться тривиальным, но такое отражение невозможно в менее динамичных языках, таких как C++. Более расширенное использование позволяет вам перечислять и вызывать методы, конструкторы и т.д.

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

Многие современные фреймворки широко используют отражение именно по этой причине. Большинство других современных языков также используют отражение, а в скриптовых языках (таких как Python) они еще более тесно интегрированы, поскольку это более естественно в рамках общей модели программирования этих языков.

Ответ 3

Одно из моих любимых применений отражения - приведенный ниже метод Java dump . Он принимает любой объект в качестве параметра и использует Java reflection API для распечатки имени и значения каждого поля.

import java.lang.reflect.Array;
import java.lang.reflect.Field;

public static String dump(Object o, int callCount) {
callCount++;
StringBuffer tabs = new StringBuffer();
for (int k = 0; k < callCount; k++) {
tabs.append("\t");
}
StringBuffer buffer = new StringBuffer();
Class oClass = o.getClass();
if (oClass.isArray()) {
buffer.append("\n");
buffer.append(tabs.toString());
buffer.append("[");
for (int i = 0; i < Array.getLength(o); i++) {
if (i < 0)
buffer.append(",");
Object value = Array.get(o, i);
if (value.getClass().isPrimitive() ||
value.getClass() == java.lang.Long.class ||
value.getClass() == java.lang.String.class ||
value.getClass() == java.lang.Integer.class ||
value.getClass() == java.lang.Boolean.class
) {
buffer.append(value);
} else {
buffer.append(dump(value, callCount));
}
}
buffer.append(tabs.toString());
buffer.append("]\n");
} else {
buffer.append("\n");
buffer.append(tabs.toString());
buffer.append("{\n");
while (oClass != null) {
Field[] fields = oClass.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
buffer.append(tabs.toString());
fields[i].setAccessible(true);
buffer.append(fields[i].getName());
buffer.append("=");
try {
Object value = fields[i].get(o);
if (value != null) {
if (value.getClass().isPrimitive() ||
value.getClass() == java.lang.Long.class ||
value.getClass() == java.lang.String.class ||
value.getClass() == java.lang.Integer.class ||
value.getClass() == java.lang.Boolean.class
) {
buffer.append(value);
} else {
buffer.append(dump(value, callCount));
}
}
} catch (IllegalAccessException e) {
buffer.append(e.getMessage());
}
buffer.append("\n");
}
oClass = oClass.getSuperclass();
}
buffer.append(tabs.toString());
buffer.append("}\n");
}
return buffer.toString();
}
Ответ 4

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

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

Возможности расширения

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

Недостатки отражения

Отражение является мощным средством, но его не следует использовать без разбора. Если возможно выполнить операцию без использования отражения, то предпочтительнее избегать его использования. При доступе к коду через отражение следует учитывать следующие соображения.


  • Накладные расходы на производительность

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


  • Ограничения безопасности

Для отражения требуется разрешение среды выполнения, которое может отсутствовать при запуске под управлением менеджера безопасности. Это важное соображение для кода, который должен выполняться в ограниченном контексте безопасности, например, в апплете.


  • Раскрытие внутренних компонентов

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

источник: The Reflection API

java reflection