предисловие
Рефлексия — это технология души лежащей в основе платформы Java. Очень важно научиться рефлексии. В этой статье мы объясним рефлексию от вводных понятий до практики, а затем до принципов. Надеюсь, она будет полезна всем.
отражение понимание
Официальный анализ
Официальный представитель Oracle о размышленияхОбъяснение:
Reflection is commonly used by programs which require the ability to examine or
modify the runtime behavior of applications running in the Java virtual machine.
This is a relatively advanced feature and should be used only by developers who
have a strong grasp of the fundamentals of the language. With that caveat in
mind, reflection is a powerful technique and can enable applications to perform
operations which would otherwise be impossible.
Явамеханизм отраженияЭто значит, что в рабочем состоянии для любого класса можно знать все свойства и методы этого класса, а для любого объекта можно вызывать любые его методы, функцией динамического получения информации и динамического вызова методов объекта становится Reflection Механизм языка Java.
Народное понимание
Орто
Все вещи имеют инь и должны иметь ян, и если есть позитив, должен быть и негатив. Раз есть отражение, то должно быть и «ортофото».
ТакОртоЧто тогда?
Когда мы пишем код, когда нам нужно использовать определенный класс, мы сначала поймем, что этот класс делает. Затем создайте экземпляр этого класса, а затем работайте с созданным объектом, которым является ортофото.
Student student = new Student();
student.doHomework("数学");
отражение
Отражение означает, что вначале мы не знаем, какой объект класса мы хотим инициализировать, и, естественно, мы не можем использовать ключевое слово new для создания объекта.
Class clazz = Class.forName("reflection.Student");
Method method = clazz.getMethod("doHomework", String.class);
Constructor constructor = clazz.getConstructor();
Object object = constructor.newInstance();
method.invoke(object, "语文");
Ортофото против отражения
Приведенные выше два фрагмента кода, эффект выполнения такой же, как показано на рисунке
Однако процесс реализации совсем другой:
- Первый фрагмент кода знает, что класс, который нужно запустить,
Student
; - Второй фрагмент кода — это запуск всей программы из строки
reflection.Student
, я знаю, что управляемый классStudent
.
в заключении
Отражение должно знать, каким классом нужно управлять во время выполнения, и может получить полную структуру класса и вызвать соответствующий метод во время выполнения.
Понимание объекта класса
Чтобы понять объект класса, давайте сначала разберемсяRTTIБар.RTTI (идентификация типа во время выполнения) идентификация типа во время выполнения, роль которого заключается в определении информации о типе и классе объекта во время выполнения.
Как Java позволяет нам идентифицировать информацию об объектах и классах во время выполнения? Есть в основном два пути: один традиционныйRRTI, который предполагает, что мы знаем все типы во время компиляции. Другой — это механизм отражения, который позволяет нам обнаруживать и использовать информацию о классе во время выполнения.
Каждый класс имеет объект классаВсякий раз, когда новый компилятор класса генерирует объект класса (более правильно, что хранится в файле .Class одинакового имени). Например, чтобы создать класс студента, то JVM создаст объект класса студента, соответствующий классу класса, в классе объект хранилищ информации, связанной с классом студента.
Роль объекта класса ClassПредоставляет или получает информацию о типе объекта во время выполнения
Основное использование отражения
Получить объект класса Class
Есть три способа получить объект Class в отражении.
Во-первых, используйте статический метод Class.forName.
Class class1 = Class.forName("reflection.TestReflection");
Во-вторых, используйте метод .class класса
Class class2 = TestReflection.class;
В-третьих, используйте метод getClass() экземпляра объекта.
TestReflection testReflection = new TestReflection();
Class class3 = testReflection.getClass();
Отражение для создания объектов, получения методов, переменных-членов, конструкторов
В этом разделе изучается базовое использование отражения в API, например методы получения, переменные-члены и т. д.
отражение создает объекты
Существует два основных способа создания объектов класса посредством отражения:
Пример кода:
//方式一
Class class1 = Class.forName("reflection.Student");
Student student = (Student) class1.newInstance();
System.out.println(student);
//方式二
Constructor constructor = class1.getConstructor();
Student student1 = (Student) constructor.newInstance();
System.out.println(student1);
результат операции:
Отражение для получения конструктора класса
Давайте посмотрим на пример:
Class class1 = Class.forName("reflection.Student");
Constructor[] constructors = class1.getDeclaredConstructors();
for (int i = 0; i < constructors.length; i++) {
System.out.println(constructors[i]);
}
Отражение для получения переменных-членов класса
Посмотреть демо:
// student 一个私有属性age,一个公有属性email
public class Student {
private Integer age;
public String email;
}
public class TestReflection {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class class1 = Class.forName("reflection.Student");
Field email = class1.getField("email");
System.out.println(email);
Field age = class1.getField("age");
System.out.println(age);
}
}
результат операции:
которыйgetField(String name)
В соответствии с именем переменной параметра вернуть конкретную переменную-член с общедоступным атрибутом, если переменнаяне является общественным достоянием, сообщается об исключении.
Метод получения класса путем отражения
demo
public class Student {
private void testPrivateMethod() {
}
public void testPublicMethod() {
}
}
public class TestReflection {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class class1 = Class.forName("reflection.Student");
Method[] methods = class1.getMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i]);
}
}
}
результат операции:
Как работает отражение
Изучив предыдущий раздел, мы уже знаем основные принципы использования API для отражения. Далее следуйте примеру, чтобы изучить цепочку выполнения метода отражения.
public class TestReflection {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("reflection.TestReflection");
Method method = clazz.getMethod("target", String.class);
method.invoke(null, "666");
}
public static void target(String str) {
//打印堆栈信息
new Exception("#" +str).printStackTrace();
System.out.println("invoke target method");
}
}
Информация стека отражает цепочку вызовов отражения:
java.lang.Exception: #666
invoke target method
at reflection.TestReflection.target(TestReflection.java:17)
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:498)
at reflection.TestReflection.main(TestReflection.java:11)
Диаграмма последовательности выполнения метода Invoke
Давайте перейдем по ссылке отражения, чтобы увидеть исходный код, сначала посмотрим на метод вызова метода:
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
//校验权限
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor(); //获取MethodAccessor
}
//返回MethodAccessor.invoke
return ma.invoke(obj, args);
}
Как видно из вышеизложенного, метод вызова метода фактически является методом вызова, который возвращает интерфейс MethodAccessor. Интерфейс MethodAccessor имеет три класса реализации. Какой класс вызывает метод вызова?
Введите методAcquireMethodAccessor, вы увидите, что MethodAccessor определяется методом newMethodAccessor ReflectionFactory.
Переходя к методу newMethodAccessor ReflectionFactory, мы видим, что возвращается объект DelegatingMethodAccessorImpl, то есть вызывается его метод вызова.
Посмотрите на метод вызова DelegatingMethodAccessorImpl.
Метод вызова DelegatingMethodAccessorImpl возвращает метод вызова MethodAccessorImpl, а метод вызова MethodAccessorImpl переопределяется его подклассом NativeMethodAccessorImpl. В настоящее время он возвращает локальный метод invoke0 следующим образом.
Поэтому метод вызова Метода определяется локальным методом invoke0, а нижний слой связан с С++.Заинтересованные друзья могут продолжить изучение.
Некоторые приложения и проблемы отражения
приложение для отражения
Отражение — это технология души Java-фреймворка, многие фреймворки используют технологию отражения, например Spring, Mybatis, Hibernate и так далее.
Соединение с базой данных JDBC
В базу данных соединений JDBC обычно включаютЗагрузите драйвер, получите соединение с базой данныхи так далее. И загрузка драйвера заключается в импорте соответствующего пакета Jar черезClass.forName()То есть технология рефлексии, драйвер, загружающий базу данных.
Использование фреймворка Spring
Spring загружает bean-компоненты через схему конфигурации XML, что также является типичным примером отражения.
Процесс загрузки:
- Загрузите внутрипрограммный файл конфигурации XML в память
- Класс Java анализирует содержимое XML-файла, чтобы получить соответствующую информацию о байт-коде.
- Используйте механизм отражения для получения экземпляра класса
- Чтобы динамически настроить свойства экземпляра, используйте
Конечно, в этом есть свои преимущества:
Нет необходимости каждый раз переходить к новому экземпляру, а файл конфигурации можно изменить, что является более гибким.
проблема с отражением
проблемы с производительностью
Производительность отражения java не очень хороша, главным образом потому, что компилятор не может оптимизировать код, связанный с отражением. Заинтересованные друзья, вы можете прочитать эту статьюjava-reflection-why-is-it-so-slow
Контрольный вопрос
Мы знаем, что в процессе разработки одноэлементного шаблона мы будем подчеркиватьСделать конструкторы закрытыми, так как это предотвращает создание объекта снаружи. Но отражение может получить поля, методы, конструкторы в классе,Изменить права доступа. Так что это не обязательно безопасно.
Давайте рассмотрим пример создания экземпляра с помощью частного конструктора через отражение.
public class Student {
private String name;
private Student(String name) {
System.out.println("我是私有构造器,我被实例化了");
this.name = name;
}
public void doHomework(String subject) {
System.out.println("我的名字是" + name);
System.out.println("我在做"+subject+"作业");
}
}
public class TestReflection {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("reflection.Student");
// 获取私有构造方法对象
Constructor constructor = clazz.getDeclaredConstructor(String.class);
// true指示反射的对象在使用时应该取消Java语言访问检查。
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance("jay@huaxiao");
student.doHomework("数学");
}
}
результат операции:
Очевидно, рефлексию можно вызывать вне зависимости от того, являетесь ли вы приватным или нет. Таким образом, использование отражения обычно требует, чтобы программа работала безограничения безопасности. Если у программы есть обязательные требования к безопасности, то лучше не использовать рефлексию.Ссылка и спасибо
- Как работает отражение
- Получите частные конструкторы через отражение и использование
- Рефлексия Java на просторечии: введение, использование, принцип
- Singleton Mode 6 шаблонов проектирования (антиотражательные атаки)
- Отражение: сценарии применения механизма отражения Java.
- Глубокое понимание информации о типе Java (объект класса) и механизма отражения
- «Идеи программирования на Java»
Личный публичный аккаунт
- Если вы хороший ребенок, который любит учиться, вы можете подписаться на мой официальный аккаунт, чтобы учиться и обсуждать вместе.
- Если вы считаете, что в этой статье есть какие-либо неточности, вы можете прокомментировать или подписаться на мой официальный аккаунт, пообщаться со мной в частном порядке, и все смогут учиться и прогрессировать вместе.