Анализ пакета java.lang.reflect

Java задняя часть JVM API

Объект (источник)

Все в Java является объектом

Объект является источником отражения

Класс является директором отражения

Класс (Директор)

Когда программа Java выполняется, JVM поддерживает уникальныйИдентификатор типа, который является объектом класса.

Базовые типы Java и ключевое слово void также соответствуют объекту класса.
Массивы элементов того же типа и размера также соответствуют объекту Class.

Есть несколько способов получить объект класса:

  • объект через .class
  • объект через метод getClass
  • Class.forName(String)

Объекты класса имеют несколько важных методов:

  • серия getConstructor, используемая для получения конструктора
  • серия getField, используемая для получения атрибутов
  • серия getMethod, используемая для получения методов

Вышеупомянутая серия включает в себя серию Declared, которая может получить все типы отражений (включая приватные) текущего объекта, но не может получить отражение родительского класса

Конструктор, Поле и Метод — три основных оружия Директора Класса, все они расположены вjava.lang.reflectДалее под пакетом будут отображаться три основных вида оружия.

Constructor

После объекта Constructor, полученного через объект Class, наиболее часто используемой операцией является создание экземпляра объекта и вызов метода newInstance.

На самом деле в объекте Class есть еще метод newInstance, который тоже можно использовать для инстанцирования объектов, в чем между ними разница?

  • Class.newInstance() может вызывать только конструктор без параметров, то есть конструктор по умолчанию, который требует, чтобы вызываемый конструктор был видимым, то есть он должен быть общедоступного типа;
  • Constructor.newInstance() может вызывать любой конструктор в соответствии с переданными параметрами. В некоторых случаях он может вызывать частный конструктор.

Demo

//Class.newInstance()
//只能调用public属性的无参构造函数  
A a = (A)Class.forName(A.class.getName()).newInstance();  

//Constructor.newInstance()
Class c= Class.forName(A.class.getName());
   
/*以下调用无参的、私有构造函数*/  
//获得无参构造
Constructor c0=c.getDeclaredConstructor();  
//设置无参构造是可访问的
c0.setAccessible(true);   
A a0=(A)c0.newInstance();
    
//调用无参构造函数,生成对象实例
/*以下调用带参的、私有构造函数*/   
Constructor c1=c.getDeclaredConstructor(new Class[]{int.class,int.class});   
c1.setAccessible(true);   
//调用有参构造函数,生成对象实例 
A a1=(A)c1.newInstance(new Object[]{5,6});   

используемые сцены:

Если вы используете интерфейсный режим, используйте new для создания объекта двери Door door = new WoodenDoor(), когда вы заменяете его другими дверями, вам нужно изменить код Door door = new OtherDoor(). Поэтому нам нужно использовать заводской режим, и мы можем производить любую дверь, которая нам нужна.Если мы используем метод newInstance() для ее создания, нам нужно только изменить файл конфигурации.

Field

После получения объекта Field через объект Class мы можем свободно просматривать и устанавливать значение атрибута объекта.

Ключевой метод:

  • get(Object object) Просмотр значения свойства определенного объекта
  • set(Object object, Object value) установить свойства для конкретного объекта
  • setAccessible (логический флаг) позволяет частным членам иметь публичные разрешения

Demo

//获取Class对象
Class aClass = MyObject.class
//通过Class对象获取Field对象
Field field = aClass.getDeclaredField("someField");
//设置可访问权限
field.setAccessible(true);

MyObject objectInstance = new MyObject();

//获取特定的对象的变量属性值
Object value = field.get(objectInstance);
//给特定对象的变量设置属性
field.set(objetInstance, value);

Поскольку Constructor, Field и Method наследуются от класса AccessibleObject, и все они имеют метод setAccessible Лично мне кажется, что setAccessible немного шпионит за конфиденциальностью, хахаха, я не знаю, что думает класс Director.

Method

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

Я полагаю, что все знакомы с вызовом, потому что многие исключения в конечном итоге найдут метод вызова.

java.lang.NullPointerException
  at ......
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:497)

invoke(Object Receiver, Object… args) можно разделить на два типа: передача параметра Receiver означает вызов метода определенного объекта, а передача null означает вызов статического метода.

//获取一个方法名为doSomesthing,参数类型为String的方法
Method method = MyObject.class.getMethod("doSomething", String.class);

//调用静态的doSomesthing方法,传递参数"parameter-value1"
Object returnValue = method.invoke(null, "parameter-value1");

Два последних слова

Эта статья является лишь кратким описанием использования объекта Clss и объектов в пакете Reflect Реализация и принцип отражения нуждаются в дальнейшем изучении. Например, объект AccessibleObject и реализация соответствующего xxxAccessor.