Java 反射 —— 运行时的类型信息

来源:互联网 发布:win10国外优化软件 编辑:程序博客网 时间:2024/05/21 16:53

1. 反射机制的由来

RTTI 机制可以告知某个对象的确切类型,但有一个前提,该类型在编译时必须已知(编译器在编译时打开和检查 .class 文件以获取类型信息)。似乎是个很宽松的限制,但假如你获取了一个指向并不在你的程序空间的对象的引用,也即编译期间无法获知该对象所属的类,等到程序真正运行起来时,才有可能。比如,在网络连接中获取了一串(事先不被预知)的字节,并被告知这些字节代表着一个类。然而该类在为你的程序生成代码之后很久才出现,那么如何在编写代码时,使用这样的类呢?

  • RTTI 与 反射的区别:
    • RTTI 需要在编译时打开和检查 .class 文件
    • 对于反射机制,.class 文件在编译时是无法获取的,所以是在运行时打开和检查 .class 文件

2. reflect 类库

Class 类库与 java.lang.reflect 类库一起对反射的概念进行了支持,该类库包含了如下三种类(每个类均实现了 Member 接口(interface Member)):

  • Field:成员变量;
  • Method:成员函数;
  • Constructor:构造器;

Java 的反射机制能获取未知类的全部成员,包括构造函数。

3. 一个实例

  • Car 类:

    package reflect;public class Car {    private String brand;    private String color;    private int maxSpeed;    public Car() {}    public Car(String brand, String color, int maxSpeed) {        this.brand = brand;        this.color = color;        this.maxSpeed = maxSpeed;    }    // getters, setters 方法}

    为了体现 java 反射机制的威力,我们不采用直接 new 的方式(有时候,比如远程过程调用 RPC,我们无法确切地知道其构造函数的参数列表)

  • ReflectTest

    package reflect;import java.lang.reflect.Constructor;import java.lang.reflect.Method;public class ReflectTest {    public static Car initByDefaultConst() throws Throwable{        ClassLoader loader = Thread.currentThread().getContextClassLoader();        Class<?> clazz = loader.loadClass("reflect.Car");        Constructor<?> cons = clazz.getDeclaredConstructor((Class[])null);        Car car = (Car)cons.newInstance();        Method setBrand = clazz.getMethod("setBrand", String.class);        setBrand.invoke(car, "红旗CA72");        Method setColor = clazz.getMethod("setColor", String.class);        setColor.invoke(car, "黑色");        Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class);        setMaxSpeed.invoke(car, 100);        return car;    }    public static void main(String[] args) throws Throwable {        Car car = initByDefaultConst();        System.out.println(car);    }}
原创粉丝点击