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

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);
    
        }
    
    }
原文地址:https://www.cnblogs.com/mtcnn/p/9421196.html