NVIDIA RTX wallpaper
594 字
3 分钟
HIT-软件构造 | Java 反射
在 Java 运行时,如果我们拿到一个 Object ,它可能是某个类的实例。如果我们想使用这个类的某个方法,却不知道这个类的名字,即连强制类型转换也做不了,那如何调用我们想要执行的方法呢。解决方案是使用 Java 反射。
Class 类与实例
如果我们有两个类 Type1 和 Type2 的实例,然后将其转换成 Object 实例。表面上我们看不出这两个 Object 实例的区别,因为我们对他们的信息一无所知,但是这只是因为他们的引用是 Object 类型的而已。
Java runtime 提供了一种数据类型,称为 Class ,Java 程序开始运行后,每次首次加载一个 class ,都会用这个 class 的信息创建一个 Class 实例,即这个 Class 实例将会包含这个类的所有信息。Object 类提供了一个接口能让我们拿到任何一个对象的 Class 实例。也就是说,对于上述的 Type1 和 Type2 转换成 Object 后的实例,我们可以拿到它们的 Class 实例,来区分这两个实例哪一个是 Type1 的实例、哪一个是 Type2 。
class Type1 { ... }
class Type2 { ... }
Type1 type1 = new Type1();
Type2 type2 = new Type2();
Object obj1 = (Object)type1;
Object obj2 = (Object)type2;
Class cls1 = obj1.getClass();
Class cls2 = obj2.getClass();除此之外,还可以已知类的名字,然后直接获得其 Class 实例:
Class cls = Type1.class;或使用包路径格式的完整类名:
Class cls = Class.forName("com.vonbrank.Type1");用 Class 实例访问字段
假设有一个类 Person ,定义如下:
class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }
}
在下面的 test 方法中,我们只能拿到它实例的 Object 引用,如果想访问 name 可以这样写:
public class Main {
    public static void main(String[] args) {
        Person person = new Person("Xiao Ming");
        test(person);
    }
    static void test(Object obj) {
        Class cls = obj.getClass();
        Field field = cls.getDeclaredField("name");
        Object value = field.get(p);
        System.out.println(value); // "Xiao Ming"
    }
}调用方法
此处我们以 String 为例展示通过反射调用对象实例的方法:
public class Main {
    public static void main(String[] args) throws Exception {
        // String对象:
        String s = "Hello world";
        // 获取String substring(int)方法,参数为int:
        Method m = String.class.getMethod("substring", int.class);
        // 在s对象上调用该方法并获取结果:
        String r = (String) m.invoke(s, 6);
        // 打印调用结果:
        System.out.println(r);
    }
}

