Android基础系列(6)Java反射

574 阅读2分钟

前言

Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。

  1. 反射的作用?
  2. 三种获取Class对象的方式
  3. 获取构造器实例化对象和属性信息
  4. 获取包信息
  5. 获取方法
  6. 小结

1 反射的作用

  • 在运行时判定任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判定任意一个类所具有的成员变量和方法;
  • 在运行时调用任意一个对象的方法;

2 三种获取Class对象的方式

第一种:Object类中的getClass()方法 第二种:类.class 第三种:通过Class类的forName()方法

// 第一种
Class<?> class1 = new Kitty().getClass();
// 第二种
Class<?> class2 = Kitty.class;
// 第三种
Class<?> class3 = Class.forName("com.ayu.demo.reflection.Kitty");

屏幕快照 2021-03-25 下午3.33.03.png

都拿到了同一个结果。

3 获取构造器实例化对象和属性信息

废话不多说,上个简单的例子。

// 猫咪类
public class Kitty {
    private String name;
    private String color;

    public Kitty() {
    }

    public Kitty(String name, String color) {
        this.name = name;
        this.color = color;
    }

    public void action() {
        System.out.println(color + name + "在卖萌");
    }
}

// 测试类
public class ReflectionTest {

    public static void main(String[] args) {
        try {
            // 第一种
            Class<?> class1 = new Kitty().getClass();
            // 获取所有的构造器
            Constructor<?>[] constructors = class1.getConstructors();
            // 获取某个构造器
            Constructor<?> constructor = class1.getConstructor(String.class, String.class);
            // 得到实例化对象
            Kitty kitty = (Kitty) constructor.newInstance("小猫咪", "白色的");
            kitty.action();

            // 获取color属性
            Field color = class1.getDeclaredField("color");
            // 跳过安全检测
            color.setAccessible(true);
            System.out.println("kitty对象color属性的值:" + color.get(kitty));
            // kitty对象中的color属性值改为【黑色的】
            color.set(kitty, "黑色的");
            kitty.action();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

代码还是比较简单的。 通过反射得到构造器,然后实例化出猫咪对象。 得到color属性,由于它是private,所以需要setAccessible(true)跳过安全检查,然后就可以拿到属性信息,或者更改。

屏幕快照 2021-03-25 下午4.11.21.png

4 获取包信息

Class<?> class1 = Kitty.class;
Package aPackage = class1.getPackage();
aPackage.getName(); // 包名

5 获取方法

Class<?> class1 = Kitty.class;
// 获取构造器
Constructor<?> constructor = class1.getConstructor(String.class, String.class);
// 得到实例化对象
Kitty kitty = (Kitty) constructor.newInstance("小猫咪", "白色的");
// 获取action方法
Method method = class1.getMethod("action");
method.invoke(kitty); // 调用action方法

如果action方法需要传入参数,则需要getMethod中声明,比如

// action方法需要传入String类型参数
public void action(String action) {
    System.out.println(color + name + action);
}

// 加上String.class
Method method = class1.getMethod("action", String.class);
method.invoke(kitty, "在打滚儿");

屏幕快照 2021-03-25 下午4.41.07.png

6 小结

  反射可以赋予JVM动态编译的能力,提升服务器性能,可以使得我们的程序更加灵活,避免写死,特别是在架构的设计中,反射是非常有用的。
  另外,反射是一种在运行时获取和使用元数据的技术,其本质在于元数据。有时间博主会继续更新相应文章。