【Java基础】了解反射

195 阅读3分钟

「这是我参与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 对象(三种)

  1. 类名.class UserEntiry.class
  2. 实例.getClass() user1.getClass()\
  3. 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");

反射构造实例化对象(两种)

  1. newInstance()

使用的默认无参构造函数

Class<UserEntity> class = UserEntity.class;
UserEntity user = class.newInstance();
-------------------------------
user.toString()---->UserEntity{age=0, friendNum=null, name='null'}
  1. 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时,才能够通过反射获取到该注解