本章主要对Java反射进行整体性介绍。

1.Java反射定义

官方定义如下:

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.

译文:

Java反射使得Java代码能够获取运行期被加载类的字段、方法和构造器的相关信息,并且能够在安全范围内对这些反射的字段、方法和构造器进行相应的操作。

2.Java反射入门示例

Java反射主要类:

  • 类:java.lang.Class;
  • 构造器:java.lang.reflect.Constructor;
  • 字段:java.lang.reflect.Field;
  • 方法:java.lang.reflect.Method;
  • 修饰符:java.lang.reflect.Modifier;

下面是入门示例代码:

ReflectDemo1.java

/**
 * 反射入门示例
 * Created by 韩超 on 2018/2/24.
 */
public class ReflectDemo1 {
    public Integer demo;

    public ReflectDemo1(Integer demo) {
        this.demo = demo;
    }

    public Integer getDemo() {
        return demo;
    }

    public void setDemo(Integer demo) {
        this.demo = demo;
    }

    @Override
    public String toString() {
        return "ReflectDemo1{" +
                "demo=" + demo +
                '}';
    }
}

ReflectIntroductionDemo.java

/**
 * Created by 韩超 on 2018/2/24.
 */
public class ReflectIntroductionDemo {

    private final static Logger LOGGER = Logger.getLogger(ReflectIntroductionDemo.class);

    /**
     * <p>Title: Java反射入门示例</p>
     * @author 韩超 2018/2/24 10:30
     */
    public static void main(String[] args) throws Exception {
        Class dClass = ReflectDemo1.class;
        LOGGER.info("获取类信息Class对象:" + dClass);

        Field field = dClass.getField("demo");
        LOGGER.info("通过Class对象 获取字段信息Field:" + field);

        Constructor constructor = dClass.getDeclaredConstructor(Integer.class);
        LOGGER.info("通过Class对象 获取构造函数Constructor: " + constructor);
        ReflectDemo1 demo1 = (ReflectDemo1) constructor.newInstance(1);
        LOGGER.info("通过Constructor对象 创建对象:" + demo1.toString());

        Method method = dClass.getDeclaredMethod("getDemo");
        LOGGER.info("通过Class对象 获取方法Method:" + method);
        Integer integer = (Integer) method.invoke(demo1);
        LOGGER.info("通过Method对象 操作对象 : public Integer getDemo() = " + integer);

        LOGGER.info("通过Class对象 获取修饰符Modifier:" + Modifier.toString(dClass.getModifiers()));
        LOGGER.info("通过Field对象 获取修饰符Modifier:" + Modifier.toString(field.getModifiers()));
        LOGGER.info("通过Method对象 获取修饰符Modifier:" + Modifier.toString(field.getModifiers()));
        LOGGER.info("通过Constructor对象 获取修饰符Modifier:" + Modifier.toString(constructor.getModifiers()));
    }
}

运行结果:

2018-02-24 13:51:35 INFO  ReflectIntroductionDemo:23 - 获取类信息Class对象:class pers.hanchao.reflect.Introduction.ReflectDemo1
2018-02-24 13:51:35 INFO  ReflectIntroductionDemo:26 - 通过Class对象 获取字段信息Field:public java.lang.Integer pers.hanchao.reflect.Introduction.ReflectDemo1.demo
2018-02-24 13:51:35 INFO  ReflectIntroductionDemo:29 - 通过Class对象 获取构造函数Constructor: public pers.hanchao.reflect.Introduction.ReflectDemo1(java.lang.Integer)
2018-02-24 13:51:35 INFO  ReflectIntroductionDemo:31 - 通过Constructor对象 创建对象:ReflectDemo1{demo=1}
2018-02-24 13:51:35 INFO  ReflectIntroductionDemo:34 - 通过Class对象 获取方法Method:public java.lang.Integer pers.hanchao.reflect.Introduction.ReflectDemo1.getDemo()
2018-02-24 13:51:35 INFO  ReflectIntroductionDemo:36 - 通过Method对象 操作对象 : public Integer getDemo() = 1
2018-02-24 13:51:35 INFO  ReflectIntroductionDemo:38 - 通过Class对象 获取修饰符Modifier:public
2018-02-24 13:51:35 INFO  ReflectIntroductionDemo:39 - 通过Field对象 获取修饰符Modifier:public
2018-02-24 13:51:35 INFO  ReflectIntroductionDemo:40 - 通过Method对象 获取修饰符Modifier:public
2018-02-24 13:51:35 INFO  ReflectIntroductionDemo:41 - 通过Constructor对象 获取修饰符Modifier:public

总结:

  • Class 类的实例表示正在运行的 Java 应用程序中的类和接口。Java反射操作基本上都是基于Class类的。
  • 获取Class类的实例有三种方式,在后续章节中再详细讲解。
  • 通过Class可以获取一个类的字段、方法和构造器,也就是Field、Method和Constructor类的实例。
  • 通过Field、Method和Constructor类的实例可以动态的操作这些字段、方法和构造器,例如创建对象、调用方法等等。

3.Java反射用途

Java反射的常见应用场景如下:

  • IDE中的各类插件:如在一个对象后面输入一个.号,IDE会自动列出相关的属性和方法等。
  • 反射机制是很多Java框架的基石:如MyBatis通过XML映射文件自动创建Dao层实例化对象等。
  • 逆向工程:例如反编译等。

4.Java反射注意事项

Java反射优点:

在运行期确定对象、绑定对象、操作对象,最大限度的发挥了Java的灵活性。

Java反射缺点:

  • 反射相当于一系列解释操作,通知jvm要做的事情,性能相对较低。
  • 反射会跳过类型检查等,导致安全性问题。例如通过反射跳过泛型的编译前类型检查。

总结:

  • 业务代码中不建议使用Java反射
  • 开发框架中一定会用到Java反射