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

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

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

1.09.2008 08:39:21
Для меня это способ получения имен классов во время выполнения и создания объектов этого класса.
Nabin 3.11.2016 05:02:17
потому что это популярный вопрос, я хотел бы отметить, что рефлексия (без аннотаций) должна быть последним инструментом, к которому вы обращаетесь при решении проблемы. Я использую это и люблю это, но это отменяет все преимущества статической типизации Java. Если вам это нужно, выделите его как можно меньше (один метод или один класс). Более приемлемо использовать его в тестах, чем производственный код. С аннотациями все должно быть в порядке - главное не указывать имена классов или методов как «Strings», если вы можете избежать этого.
Bill K 4.04.2017 21:45:45
givanse 20.04.2018 22:34:46
В дополнение к комментарию @ BillK: Отражение очень мощное, я бы назвал его магическим. С большой властью приходит большая ответственность. Используйте его, только если вы знаете, что делаете.
MC Emperor 22.11.2018 13:02:56
Вы можете избежать многих ловушек, связанных с отражением, используя коллектор @Jailbreak. Он обеспечивает прямой, безопасный с точки зрения типов доступ к закрытым полям, методам и т. Д. Позвольте компилятору Java безопасно проверить ваш код и позволить Manifold генерировать для вас базовый доступ к отражению. Узнайте больше: manifold.systems/docs.html#type-safe-reflection
Scott 15.12.2018 00:54:05
21 ОТВЕТ
РЕШЕНИЕ

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

Например, скажем, у вас есть объект неизвестного типа в 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 ++

1704
7.03.2020 23:08:52
Можете ли вы объяснить, каково значение этого нулевого параметра в этой строке Method method = foo.getClass (). getMethod ("doSomething", null);
Krsna Chaitanya 23.11.2012 05:59:37
Нулевое значение указывает, что в метод foo не переданы параметры. См. Docs.oracle.com/javase/6/docs/api/java/lang/reflect/… , java.lang.Object ...) для подробностей.
Matt Sheppard 27.11.2012 01:14:19
Просто чтобы прояснить, так как это имеет так много голосов. Способность проверять код в системе и видеть типы объектов - это не отражение, а самоанализ типа. Отражение - это возможность вносить изменения во время выполнения, используя интроспекцию. Различие здесь необходимо, так как некоторые языки поддерживают самоанализ, но не поддерживают рефлексию. Одним из таких примеров является C ++.
bigtunacan 12.03.2013 03:46:31
Мне нравится рефлексия, но если у вас есть контроль над кодом, то использование рефлексии, как указано в этом ответе, неоправданно и, следовательно, является злоупотреблением - вы должны использовать тип Introspection (instanceof) и строгие типы. Если есть что-то кроме размышления, чтобы сделать что-то, это то, как это нужно сделать. Отражение вызывает серьезную душевную боль, потому что вы теряете все преимущества использования статически типизированного языка. Если вам это нужно, вам это нужно, однако даже тогда я бы рассмотрел готовое решение, такое как Spring, или что-то, что полностью инкапсулирует необходимое отражение - IE: пусть у кого-то еще будут головные боли.
Bill K 29.07.2013 15:50:01
@bigtunacan Откуда вы взяли эту информацию? Я вижу термин «отражение», используемый в официальной документации Java от Oracle, чтобы описать не только возможность вносить изменения во время выполнения, но также и способность видеть тип объекта. Не говоря уже , что большинство так называемых «типа интроспекции» связанных классов (например: Method, Constructor, Modifier, Field, Member, в основном , по- видимому все , кроме Class) находятся в пределах java.lang.*reflect*пакета. Возможно, понятие «отражение» всесторонне включает как «самоанализ типа», так и модификацию во время выполнения?
RestInPeace 29.04.2016 09:34:26

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

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

Например, в C # вы можете загрузить сборку (.dll) во время выполнения, исследовать ее, перемещаться по классам и выполнять действия в соответствии с тем, что вы нашли. Он также позволяет создавать экземпляр класса во время выполнения, вызывать его метод и т. Д.

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

15
27.03.2020 20:37:23

Не каждый язык поддерживает рефлексию, но принципы обычно одинаковы в языках, которые его поддерживают.

Отражение - это способность «отражать» структуру вашей программы. Или более конкретно. Чтобы взглянуть на имеющиеся у вас объекты и классы и программно получить информацию о методах, полях и интерфейсах, которые они реализуют. Вы также можете посмотреть на такие вещи, как аннотации.

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

36
1.09.2008 08:50:57
Мне нужно создавать экземпляры объектов на основе данных, представленных в БД. Я считаю, что это то, о чем вы говорите. Пример кода очень мне поможет. Заранее спасибо.
Atom 22.06.2015 18:45:41

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

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

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

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

240
24.01.2016 00:36:55
Другими словами, вы можете создать экземпляр из его квалифицированного имени, и компилятор не будет жаловаться на это (потому что, скажем, вы используете просто String для имени класса). Затем, во время выполнения, если этот класс отсутствует, вы получите исключение. Вы вроде обошли компилятор в этом случае. Не могли бы вы дать мне конкретный вариант использования для этого? Я просто не могу представить, когда выберу это.
Fernando Gabrieli 1.12.2018 21:40:04
@FernandoGabrieli, хотя верно, что с помощью отражения легко создавать ошибки времени выполнения, также вполне возможно использовать отражение, не рискуя исключениями времени выполнения. Как указывалось в моем ответе, обычное использование рефлексии - для библиотек или структур, которые явно не могут знать структуру приложения во время компиляции, поскольку они компилируются отдельно от приложения. Любая библиотека, которая использует «код по соглашению», вероятно, будет использовать отражение, но не обязательно использовать магические строки.
Liedman 15.01.2019 12:25:34
C++действительно имеет информацию о типе времени выполнения. RTTI
Ayxan 10.12.2019 20:32:10

Reflection - это ключевой механизм, позволяющий приложению или среде работать с кодом, который еще не был написан!

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

Другим примером может быть Java API для синтаксического анализа XML (JAXP) . Где поставщик синтаксического анализатора XML подключается через хорошо известные системные свойства, которые используются для создания новых экземпляров посредством отражения.

И, наконец, наиболее полный пример - это Spring, который использует отражение для создания своих компонентов и для интенсивного использования прокси.

43
1.09.2008 09:30:55

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

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();
}
112
29.01.2019 00:08:22
На что должен быть установлен Callcount?
Tom 29.04.2010 13:06:11
Я получил исключение в потоке "AWT-EventQueue-0" java.lang.StackOverflowError, когда я запустил это.
Tom 29.04.2010 13:13:21
@Tom callCountдолжен быть установлен на ноль. Это значение используется для определения того, сколько вкладок должно предшествовать каждой строке вывода: каждый раз, когда дампу необходимо вывести «подобъект», выходные данные будут печататься как вложенные в родительский объект. Этот метод оказывается полезным, когда обернут в другой. Посмотрим printDump(Object obj){ System.out.println(dump(obj, 0)); }.
fny 23.11.2012 06:09:31
Java.lang.StackOverflowError может быть создан в случае циклических ссылок из-за непроверенной рекурсии: buffer.append (dump (value, callCount))
Arnaud P 1.07.2013 23:03:02
Можете ли вы специально опубликовать свой код в Public Domain, пожалуйста?
stolsvik 8.10.2013 10:06:27

Согласно моему пониманию:

Отражение позволяет программисту динамически получать доступ к объектам в программе. то есть при кодировании приложения, если программист не знает о классе или его методах, он может использовать этот класс динамически (во время выполнения) с помощью отражения.

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

Вместо этого, используя рефлексию, нужно беспокоиться о возможном изменении имени класса.

15
2.04.2013 16:30:06

Пример:

Возьмем, к примеру, удаленное приложение, которое дает вашему приложению объект, который вы получаете с помощью их методов API. Теперь, основываясь на объекте, вам может потребоваться выполнить какое-то вычисление.

Поставщик гарантирует, что объект может быть 3-х типов, и нам нужно выполнять вычисления в зависимости от типа объекта.

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

21
14.08.2019 14:55:43
Мне нужно что-то подобное .. Пример очень мне поможет, так как я новичок в понятиях рефлексии ..
Atom 22.06.2015 18:42:11
Я в замешательстве: вы не можете использовать instanceofдля определения типа объекта во время выполнения?
ndm13 11.01.2018 02:09:37

Reflectionимеет много применений . Тот, с которым я больше знаком, - это возможность создавать код на лету.

IE: динамические классы, функции, конструкторы - на основе любых данных (xml / array / sql results / hardcoded / etc ..)

6
23.06.2015 05:47:19
Этот ответ был бы намного лучше, если бы вы дали только один необычный пример сгенерированного кода либо из результата SQL, либо из файла XML и т. Д.
ThisClark 15.02.2017 01:53:59
Нет проблем. Я использовал отражение в приложении Windows, которое динамически генерирует интерфейс на основе XML, взятого из базы данных.
Ess Kay 16.02.2017 18:41:11
В общем, я создал класс, который показывает пользователю отчет. Этот отчет имеет такие параметры, как Date (from to) id или что-то еще. Эта информация хранится в XML. Итак, сначала у нас есть выбор отчета. На основе выбранного отчета форма получает XML. После извлечения xml он использует отражение для создания класса с полями, основанными на отраженных типах. После того, как вы перейдете на другой отчет, планшет будет очищен, и на основе xml будут созданы новые поля. Так что, по сути, это динамическая форма, основанная на рефлексии. Я также использовал другие способы, но это должно быть достаточно Надежда, которая помогает
Ess Kay 16.02.2017 18:45:10

Reflection позволяет создавать экземпляры новых объектов, вызывать методы и операции get / set с переменными класса динамически во время выполнения, не имея предварительных знаний о его реализации.

Class myObjectClass = MyObject.class;
Method[] method = myObjectClass.getMethods();

//Here the method takes a string parameter if there is no param, put null.
Method method = aClass.getMethod("method_name", String.class); 

Object returnValue = method.invoke(null, "parameter-value1");

В приведенном выше примере нулевой параметр - это объект, для которого вы хотите вызвать метод. Если метод статический, вы вводите ноль. Если метод не является статическим, то при вызове вам нужно предоставить действительный экземпляр MyObject вместо null.

Отражение также позволяет вам получить доступ к закрытому члену / методам класса:

public class A{

  private String str= null;

  public A(String str) {
  this.str= str;
  }
}

,

A obj= new A("Some value");

Field privateStringField = A.class.getDeclaredField("privateString");

//Turn off access check for this field
privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(obj);
System.out.println("fieldValue = " + fieldValue);
  • Для проверки классов (также называемых самоанализом) вам не нужно импортировать пакет отражения ( java.lang.reflect). Метаданные класса могут быть доступны через java.lang.Class.

Reflection - очень мощный API, но он может замедлить работу приложения, если используется в избытке, так как он разрешает все типы во время выполнения.

34
8.07.2013 18:25:33

Java Reflection довольно мощный и может быть очень полезным. Отражение Java позволяет проверять классы, интерфейсы, поля и методы во время выполнения, не зная имен классов, методов и т. Д. Во время компиляции. Также возможно создавать новые объекты, вызывать методы и получать / устанавливать значения полей, используя отражение.

Быстрый пример Java Reflection, чтобы показать вам, как выглядит отражение:

Method[] methods = MyObject.class.getMethods();

    for(Method method : methods){
        System.out.println("method = " + method.getName());
    }

Этот пример получает объект Class из класса MyObject. Используя объект класса, пример получает список методов этого класса, выполняет итерацию методов и выводит их имена.

Как все это работает объясняется здесь

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

  • Spring использует конфигурацию бина, такую ​​как:


<bean id="someID" class="com.example.Foo">
    <property name="someField" value="someValue" />
</bean>

Когда контекст Spring обрабатывает этот элемент <bean>, он будет использовать Class.forName (String) с аргументом "com.example.Foo" для создания экземпляра этого класса.

Затем он снова будет использовать отражение, чтобы получить соответствующий установщик для элемента <property> и установить его значение в указанное значение.

  • Junit использует Reflection специально для тестирования частных / защищенных методов.

Для частных методов,

Method method = targetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

Для частных полей

Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);
21
26.08.2015 06:38:04

Я просто хочу добавить некоторые моменты ко всему, что было перечислено.

С помощью Reflection API вы можете написать универсальный toString()метод для любого объекта.

Это полезно при отладке.

Вот несколько примеров:

class ObjectAnalyzer {

   private ArrayList<Object> visited = new ArrayList<Object>();

   /**
    * Converts an object to a string representation that lists all fields.
    * @param obj an object
    * @return a string with the object's class name and all field names and
    * values
    */
   public String toString(Object obj) {
      if (obj == null) return "null";
      if (visited.contains(obj)) return "...";
      visited.add(obj);
      Class cl = obj.getClass();
      if (cl == String.class) return (String) obj;
      if (cl.isArray()) {
         String r = cl.getComponentType() + "[]{";
         for (int i = 0; i < Array.getLength(obj); i++) {
            if (i > 0) r += ",";
            Object val = Array.get(obj, i);
            if (cl.getComponentType().isPrimitive()) r += val;
            else r += toString(val);
         }
         return r + "}";
      }

      String r = cl.getName();
      // inspect the fields of this class and all superclasses
      do {
         r += "[";
         Field[] fields = cl.getDeclaredFields();
         AccessibleObject.setAccessible(fields, true);
         // get the names and values of all fields
         for (Field f : fields) {
            if (!Modifier.isStatic(f.getModifiers())) {
               if (!r.endsWith("[")) r += ",";
               r += f.getName() + "=";
               try {
                  Class t = f.getType();
                  Object val = f.get(obj);
                  if (t.isPrimitive()) r += val;
                  else r += toString(val);
               } catch (Exception e) {
                  e.printStackTrace();
               }
            }
         }
         r += "]";
         cl = cl.getSuperclass();
      } while (cl != null);

      return r;
   }    
}
11
20.09.2014 22:22:03

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

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

Особенности расширяемости

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

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

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

  • Накладные расходы

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

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

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

  • Воздействие внутренних органов

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

источник: Reflection API

82
24.07.2018 17:20:41

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

public class Test {

    public void firstMoveChoice(){
        System.out.println("First Move");
    } 
    public void secondMOveChoice(){
        System.out.println("Second Move");
    }
    public void thirdMoveChoice(){
        System.out.println("Third Move");
    }

    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 
        Test test = new Test();
        Method[] method = test.getClass().getMethods();
        //firstMoveChoice
        method[0].invoke(test, null);
        //secondMoveChoice
        method[1].invoke(test, null);
        //thirdMoveChoice
        method[2].invoke(test, null);
    }

}
18
14.08.2019 14:56:25

Отражение - позволить объекту увидеть их внешний вид. Этот аргумент, похоже, не имеет ничего общего с рефлексией. На самом деле, это способность «самоидентифицироваться».

Отражение само по себе является словом для таких языков, которые не обладают способностью к самопознанию и самоощущению, как Java и C #. Поскольку у них нет способности к самопознанию, когда мы хотим наблюдать, как это выглядит, у нас должна быть другая вещь, чтобы подумать о том, как это выглядит. Отличные динамические языки, такие как Ruby и Python, могут воспринимать свое отражение без помощи других людей. Можно сказать, что объект Java не может воспринимать, как он выглядит без зеркала, которое является объектом класса отражения, но объект в Python может воспринимать его без зеркала. Вот почему нам нужно отражение в Java.

11
24.07.2018 17:22:16
type (), isinstance (), callable (), dir () и getattr (). .... это призывы к
AnthonyJClink 30.01.2018 16:14:22

Со страницы документации Java

java.lang.reflectПакет предоставляет классы и интерфейсы для получения отражающей информации о классах и объектах. Reflection обеспечивает программный доступ к информации о полях, методах и конструкторах загруженных классов, а также использование отраженных полей, методов и конструкторов для работы с их соответствующими аналогами в рамках ограничений безопасности.

AccessibleObjectпозволяет подавить проверки доступа, если необходимо ReflectPermission.

Классы в этом пакете, наряду с java.lang.Classприложениями, такими как отладчики, интерпретаторы, инспекторы объектов, браузеры классов и службы, такие как Object Serializationи JavaBeansкоторым требуется доступ либо к открытым членам целевого объекта (на основе его класса времени выполнения), либо к членам, объявленным данный класс

Включает в себя следующие функции.

  1. Получение объектов класса,
  2. Изучение свойств класса (поля, методы, конструкторы),
  3. Установка и получение значений полей,
  4. Вызывая методы,
  5. Создание новых экземпляров объектов.

Посмотрите на эту ссылку на документацию для методов, предоставляемых Classклассом.

Из этой статьи (Деннис Сосноски, президент Sosnoski Software Solutions, Inc) и этой статьи (pdf-исследования безопасности):

Я вижу значительные недостатки, чем использование отражения

Пользователь Reflection:

  1. Это обеспечивает очень универсальный способ динамического связывания программных компонентов.
  2. Это полезно для создания библиотек, которые работают с объектами очень общими способами.

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

  1. Отражение намного медленнее, чем прямой код, когда используется для доступа к полям и методам.
  2. Это может скрыть то, что на самом деле происходит внутри вашего кода
  3. Обход исходного кода может создать проблемы с обслуживанием
  4. Код отражения также более сложен, чем соответствующий прямой код
  5. Это позволяет нарушать ключевые ограничения безопасности Java, такие как защита доступа к данным и безопасность типов

Общие нарушения:

  1. Загрузка ограниченных классов,
  2. Получение ссылок на конструкторы, методы или поля ограниченного класса,
  3. Создание новых экземпляров объекта, вызов методов, получение или установка значений полей ограниченного класса.

Посмотрите на этот вопрос SE, касающийся злоупотребления функцией отражения:

Как мне прочитать приватное поле в Java?

Резюме:

Небезопасное использование его функций из системного кода также может легко привести к компрометации режима безопасности Java l. Так что используйте эту функцию экономно

9
23.05.2017 12:34:53
Чтобы избежать проблем с производительностью Reflection в некоторых случаях, нужно, чтобы класс Woozleпроверял другие классы при запуске, чтобы увидеть, какие из них имеют статический RegisterAsWoozleHelper()метод, и вызывал все такие методы, которые он находит, с помощью обратного вызова, который они могут использовать, чтобы рассказать Woozleо себе, избегая необходимо использовать отражение при десериализации данных.
supercat 1.02.2020 18:53:01

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

7
24.07.2018 17:22:09

Reflection - это API, который используется для проверки или изменения поведения методов, классов, интерфейсов во время выполнения.

  1. Необходимые классы для размышления представлены в разделе java.lang.reflect package.
  2. Reflection дает нам информацию о классе, к которому принадлежит объект, а также о методах этого класса, которые могут быть выполнены с помощью объекта.
  3. Через отражение мы можем вызывать методы во время выполнения независимо от спецификатора доступа, используемого с ними.

java.langИ java.lang.reflectпакеты обеспечивают классы для Java Reflection.

Отражение может быть использовано для получения информации о -

  1. КлассgetClass() метод используется , чтобы получить имя класса , к которому принадлежит объект.

  2. КонструкторыgetConstructors() метод используется для получения государственных конструкторов класса , к которому принадлежит объект.

  3. МетодыgetMethods() метод используется для получения общих методов класса , к которой принадлежит объекты.

Reflection API используется в основном:

IDE (интегрированная среда разработки), например Eclipse, MyEclipse, NetBeans
и т. Д. Средства отладки и тестирования и т. Д.

Преимущества использования отражения:

Функции расширяемости. Приложение может использовать внешние пользовательские классы, создавая экземпляры объектов расширяемости, используя их полностью определенные имена.

Инструменты отладки и тестирования. Отладчики используют свойство отражения для проверки закрытых членов на классах.

Недостатки:

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

Воздействие внутренних элементов: рефлексивный код нарушает абстракции и, следовательно, может изменить поведение при обновлении платформы.

Ссылка: Java Отражение javarevisited.blogspot.in

17
22.03.2017 07:27:08
Я бы добавил к недостаткам " Это нарушает рефакторинг ". Для меня это главная причина, чтобы как можно больше избегать размышлений.
SantiBailors 20.12.2017 11:27:33
Таким образом, это позволяет нам (например) проверять классы, которые у нас есть (есть ли у нас их экземпляры или нет), правильно? Под этим я подразумеваю получение их методов или конструкторов и использование их для создания новых экземпляров / их вызова. Почему мы говорим «изменение поведения программы», если поведение уже есть, но с другим кодом? Почему это называется «отражение»? Спасибо
Fernando Gabrieli 1.12.2018 21:28:04

Как и предполагает само имя, оно отражает то, что оно содержит, например, метод класса и т. Д., Кроме предоставления возможности динамического вызова экземпляра метода, создающего экземпляр во время выполнения.

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

9
9.04.2017 02:29:34

Я хочу ответить на этот вопрос примером. Прежде всего, Hibernateпроект использует Reflection APIгенерацию CRUDоператоров для преодоления пропасти между запущенным приложением и хранилищем сохраняемости. Когда вещи изменяются в домене, Hibernateони должны знать о них, чтобы сохранить их в хранилище данных и наоборот.

Альтернативно работает Lombok Project. Он просто внедряет код во время компиляции, в результате код вставляется в классы вашего домена. (Я думаю, что это нормально для добытчиков и сеттеров)

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

А из Java 7 у нас есть MethodHandles, который работает как Reflection API. В проектах для работы с регистраторами мы просто копируем и вставляем следующий код:

Logger LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass().getName());

Потому что в этом случае сложно сделать опечатку.

3
5.12.2018 06:35:57

Как мне кажется, лучше объяснить на примере, и ни один из ответов, похоже, не делает этого ...

Практическим примером использования отражений может быть языковой сервер Java, написанный на Java, или языковой сервер PHP, написанный на PHP, и т. Д. Language Server предоставляет вашим IDE такие возможности, как автозаполнение, переход к определению, контекстная помощь, типы подсказок и многое другое. Чтобы все имена тегов (слова, которые могут быть автоматически заполнены) отображать все возможные совпадения при вводе текста, языковой сервер должен проверять все, что касается класса, включая блоки документов и закрытые члены. Для этого нужно отражение указанного класса.

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

3
24.06.2019 12:51:51