Рефлексия: душа веб-обучения
От начального javac -HelloWorld.java до объектно-ориентированной части мы можем разделить этапы, которые Java-код проходит на компьютере, на три части:Этап исходного кода——Этап объекта класса класса——Стадия выполненияИ мы знаем, что класс в Java хранится на жестком диске в стадии исходного кода, и после компиляции он загружается в область памяти, так есть ли способ получить или изменить его в данном случае метод или свойство? Вот о чем мы сегодня говоримМеханизм отражения Java
(A) Обзор и преимущества
(1 Обзор
Механизм отражения JAVA находится вРабочий статусДля любого класса можно знать все свойства и методы этого класса, для любого объекта можно вызывать любые его методы и свойства.Динамически получаемая информациятак же какДинамический объект вызоваФункция метода называетсяМеханизм отражения языка java. --Энциклопедия Baidu
Мы делим класс на три части: переменные-члены, методы построения, методы-члены, после компиляции кода он становится файлом байт-кода (файл .class), и все является объектом, поэтому в файле байт-кода эти три части интегрированы в объекты по отдельности, поэтому делаем вывод:
Отражение: инкапсулируйте различные компоненты класса в объекты и используйте объект этого типа класса для использования переменных-членов, конструкторов и методов-членов в файле.
(2) Преимущества
- есть в программе"Время выполнения",правильно.classфайл для работы и, таким образом, для получения и управления различными частями класса
- Может быть разделен для улучшения масштабируемости программы
- Повышение гибкости процедуры (показано в последнем случае)
(2) Как получить объект класса
(1) Загрузите файл байт-кода в память и верните объект класса.В основном используется в файлах конфигурации, имя класса определяется в файле конфигурации. прочитать файл, загрузить класс
Class.forName("全类名")
(2) В основном используется для передачи параметров
类名.class
(3) Метод getClass() определен в классе Object.В основном используется для способа получения байт-кода объекта.
对象.getClass():
Три способа реализации кода
package cn.ideal.reflect;
import cn.ideal.domain.Student;
public class ReflectDemo1 {
public static void main(String[] args) throws Exception {
//1.Class.forName("全类名")
Class cls1 = Class.forName("cn.ideal.domain.Student");
System.out.println(cls1);
//2.类名.class
Class cls2 = Student.class;
System.out.println(cls2);
//3.对象.getClass()
Student p = new Student();
Class cls3 = p.getClass();
System.out.println(cls3);
//用 == 比较
System.out.println(cls1 == cls2);//true
System.out.println(cls2 == cls3);//true
}
}
//运行结果
class cn.ideal.domain.Student
class cn.ideal.domain.Student
class cn.ideal.domain.Student
true
true
Из приведенного выше случая мы можем сделать вывод:
Один и тот же файл байт-кода (*.class) загружается только один раз во время работы программы, и объект класса, полученный любым методом, один и тот же.
(3) Функция объекта класса
(1) Получить функцию:
получить переменные-члены
//获取所有public修饰的成员变量
Field[] getFields()
//获取指定名称的public修饰的成员变量
Field getField(String name)
//获取所有的成员变量,不考虑修饰符
Field[] getDeclaredFields()
Field getDeclaredField(String name)
конструкторы
Constructor<?>[] getConstructors()
Constructor<T> getConstructor(类<?>... parameterTypes)
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
Constructor<?>[] getDeclaredConstructors()
получить методы-члены
Method[] getMethods()
Method getMethod(String name, 类<?>... parameterTypes)
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name, 类<?>... parameterTypes)
получить полное имя класса
String getName()
Поле: переменная-член
操作:
//设置值
void set(Object obj, Object value)
//获取值
get(Object obj)
//忽略访问权限修饰符的安全检查
setAccessible(true):暴力反射
Конструктор: Конструктор
创建对象:
T newInstance(Object... initargs)
如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
Метод: объект метода
//执行方法
Object invoke(Object obj, Object... args)
//获取方法名称
String getName:获取方法名
Давайте подробно рассмотрим некоторые из вышеперечисленных методов.
package cn.ideal.reflect;
import cn.ideal.domain.Student;
import java.lang.reflect.Field;
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
//获取Student的Class对象
Class studentClass = Student.class;
/*
1. 获取成员变量们
* Field[] getFields()
* Field getField(String name)
* Field[] getDeclaredFields()
Field getDeclaredField(String name)
*/
//Field[] getFields() 获取所有public修饰的成员变量
Field[] fields = studentClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("----------");
//Field getField(String name)
Field a = studentClass.getField("a");
//获取成员变量a的值
Student s = new Student();
Object value = a.get(s);
System.out.println(value);
//设置a的值
a.set(s, "张三");
System.out.println(s);
System.out.println("----------");
//Field[] getDeclaredFields() 获取所有的成员变量
Field[] declaredFields = studentClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("----------");
//Field getDeclaredField(String name)
Field d = studentClass.getDeclaredField("d");
//忽略访问权限修饰符
d.setAccessible(true);//暴力反射
Object value2 = d.get(s);
System.out.println(value2);
}
}
//运行结果
public java.lang.String cn.ideal.domain.Student.a
----------
null
Student{name='null', age=0, a='张三', b='null', c='null', d='null'}
----------
private java.lang.String cn.ideal.domain.Student.name
private int cn.ideal.domain.Student.age
public java.lang.String cn.ideal.domain.Student.a
protected java.lang.String cn.ideal.domain.Student.b
java.lang.String cn.ideal.domain.Student.c
private java.lang.String cn.ideal.domain.Student.d
----------
null
package cn.ideal.reflect;
import cn.ideal.domain.Student;
import java.lang.reflect.Constructor;
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
//获取Student的Class对象
Class studentClass = Student.class;
/*
2. 获取构造方法们
* Constructor<?>[] getConstructors()
* Constructor<T> getConstructor(类<?>... parameterTypes)
* Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
* Constructor<?>[] getDeclaredConstructors()
*/
//Constructor<T> getConstructor(类<?>... parameterTypes)
Constructor constructor = studentClass.getConstructor(String.class, int.class);
System.out.println(constructor);
//创建对象 带参
Object student = constructor.newInstance("张三", 20);
System.out.println(student);
System.out.println("----------");
Constructor constructor1 = studentClass.getConstructor();
System.out.println(constructor1);
//创建对象 不带参
Object student1 = constructor1.newInstance();
System.out.println(student1);
//创建对象 不带参 (推荐方法)
Object o = studentClass.newInstance();
System.out.println(o);
}
}
package cn.ideal.reflect;
import cn.ideal.domain.Student;
import java.lang.reflect.Method;
public class ReflectDemo4 {
public static void main(String[] args) throws Exception {
//获取Student的Class对象
Class studentClass = Student.class;
/*
3. 获取成员方法们:
* Method[] getMethods()
* Method getMethod(String name, 类<?>... parameterTypes)
* Method[] getDeclaredMethods()
* Method getDeclaredMethod(String name, 类<?>... parameterTypes)
*/
//获取指定名称的方法
Method study_method = studentClass.getMethod("study");
Student s = new Student();
//执行方法
study_method.invoke(s);
Method study_method2 = studentClass.getMethod("study", String.class);
//执行方法
study_method2.invoke(s, "英语");
System.out.println("----------");
//获取所有public修饰的方法
Method[] methods = studentClass.getMethods();
for (Method method : methods) {
System.out.println(method);
String name = method.getName();
System.out.println(name);
}
//获取类名
String className = studentClass.getName();
System.out.println(className);
}
}
(4) Корпус отражения
Изменяя файл конфигурации, нельзя изменить код класса, можно создавать объекты любого класса и выполнять любой метод, избегая неудобств, связанных с постоянным изменением файла класса, и улучшая расширяемость программы.
* 实现:
1. 配置文件
2. 反射
* 步骤:
1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
2. 在程序中加载读取配置文件
3. 使用反射技术来加载类文件进内存
4. 创建对象
5. 执行方法
//pro.properties 自定义配置文件
className=cn.ideal.domain.Student
methodName=study
package cn.ideal.reflect;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectTest {
public static void main(String[] args) throws Exception {
/*
不改变该类的任何代码,可以创建任意类的对象,可以执行任意方法
*/
//1.加载配置文件
//创建Properties对象
Properties pro = new Properties();
//加载配置文件,转换为一个集合
//获取class目录下的配置文件
ClassLoader classLoader = ReflectTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("pro.properties");
pro.load(is);
//2.获取配置文件中定义的数据
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//3.加载该类进内存
Class cls = Class.forName(className);
//4.创建对象
Object obj = cls.newInstance();
//5.获取方法对象
Method method = cls.getMethod(methodName);
//6.执行方法
method.invoke(obj);
}
Я лишь поверхностно рассказал об основных знаниях об отражении.Некоторые из более глубоких знаний будут объяснены в специальной статье позже из-за проблем с пространством.Спасибо за вашу поддержку. Недостатков действительно много, и я надеюсь поделиться с вами.
конец:
Если есть какие-либо недостатки в содержании или неправильные места, пожалуйста, оставьте мне сообщение, чтобы оставить комментарии! ^_^
Если это может вам помочь, то следуйте за мной! (Серия статей будет обновляться по мере возможности на официальном аккаунте)
Мы не знаем друг друга здесь, но мы все усердно работаем над своей мечтой ❤
Публичный аккаунт, настаивающий на продвижении оригинальной технологии Java: в идеале — более двух дней.