「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战」
反射是什么?
【反射】提供了在程序运行过程中动态获取类信息和调用类方法。
例如:可以通过反射获取类的构造方法,进行类实例的构造
反射主要组成部分
-
Class:Class类对象包含对象所有信息
-
Field:Class类中用来描述类属性。(数据类型、属性名、访问修饰符)
-
Constructor:Class类中用来描述类构造方法。(参数类型、参数方法、访问修饰符)
-
Method:Class类中用来描述类方法。类似构造方法,但多了返回值类型信息了
反射 API
【Field】属性
- Field[] getFields():获取类中所有被public修饰的所有变量
- Field getField(String name):根据变量名获取类中的一个变量,该变量必须被public修饰
- Field[] getDeclaredFields():获取类中所有的变量,但无法获取继承下来的变量
- Field getDeclaredField(String name):根据姓名获取类中的某个变量无法获取继承下来的变量
Declared 细分
其他信息内部类同理
有Declared修饰的方法:可以获取该类内部包含的所有变量、方法和构造器,但是无法获取继承下来的信息
无Declared修饰的方法:可以获取该类中public修饰的变量、方法和构造器,可获取继承下来的信息
反射常见应用
反射中的用法有非常非常多,常见的功能有以下这几个:
- 在运行时获取一个类的 Class 对象
- 在运行时构造一个类的实例化对象
- 在运行时获取一个类的所有信息:变量、方法、构造器、注解
反射获取类的 Class 对象(三种)
- 类名.class UserEntiry.class
- 实例.getClass() user1.getClass()\
- Class.forName(className-类全限定名(路径))*
类名.class
Class<UserEntity> class = UserEntity.class;
实例.getClass()
UserEntity userEntity = new UserEntity();
Class<? extends UserEntity> class = userEntity.getClass();
Class.forName()
Class<?> class = Class.forName("com.entity.UserEntity");
反射构造实例化对象(两种)
- newInstance()
使用的默认无参构造函数
Class<UserEntity> class = UserEntity.class;
UserEntity user = class.newInstance();
-------------------------------
user.toString()---->UserEntity{age=0, friendNum=null, name='null'}
- Constructor构造器
调用带参构造器
Class<UserEntity> class = UserEntity.class;
Constructor<? extends UserEntity> constructor = class.getConstructor(int.class, Integer.class, String.class);
constructor.setAccessible(true);//忽略访问修饰符的检查
UserEntity constructorUser = constructor.newInstance(21, 2, "小明");
获取类所有信息:变量、方法、构造器、注解
【方法】
UserEntity实体类上加新的方法,提供反射调用
public void getInfo() {
System.out.println("UserEntity{" +
"age=" + age +
", friendNum=" + friendNum +
", name='" + name + ''' +
'}');
}
Method getInfo = class.getMethod("getInfo");
// 第一个参数是 指定调用该方法的对象,第二个参数是 方法参数列表
getInfo.invoke(constructorUser,null);
------------------------------------------
输出:UserEntity{age=21, friendNum=2, name='小明'}
【变量】
获取 UserEntity实体类变量的名称
// 得到变量数组
Field[] fields = class.getDeclaredFields();
for (Field field : fields) {
System.out.println("field.getName() = " + field.getName());
}
-------------------------------------
输出:field.getName() = age
field.getName() = friendNum
field.getName() = name
【注解】
实体类属性添加注解
@Value(1)
private int age;
Field[] fields = class.getDeclaredFields();
for (Field field : fields) {
// 判断变量上的注解类型为 Value.calss
if (field.getAnnotation(Value.class) instanceof Value) {
System.out.println("field.getName() = " + field.getName());
System.out.println("field.getAnnotation(Value.class).value() = " + field.getAnnotation(Value.class).value());
}
}
------------------------------------------
输出:
field.getName() = age
field.getAnnotation(Value.class).value() = 1
注意:
只有注解的@Retension标注为RUNTIME时,才能够通过反射获取到该注解