欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java反射机制

程序员文章站 2022-05-23 19:35:19
...

一、简介

百度百科:Java反射机制实在运行状态中,对任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意的方法和属性,这种动态获取信息以及动态调用对象的方法的功能成为Java语言的反射机制。

适用场景:在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实际上有很多设计、开发都与反射机制有关,例如模块化的开发,通过反射去调用对应的字节码;动态代理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架,也是利用CGLIB 反射机制才得以实现,其中运用最多的场景是JDBC 的数据库的连接。

反射机制的优点

  • 降低模块的耦合性,提高程序灵活性、扩展性。

反射机制的缺点

  • 性能差:反射包括了一些动态类型,所以JVM无法对这些代码进行优化。因此,反射操作的效率比非反射操作低很多。在执行代码效率很高的程序中要避免使用反射。
  • 安全限制:使用反射技术要求程序必须在一个没有安全限制的环境中运行。
  • 内部暴漏:由于反射允许执行一些在正常情况下不被允许的操作(比如访问私有属性和方法),所以使用反射可能会导致意料之外的副作用——代码有功能上的错误,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着改变。

二、Java代码实现

插件类PlugIn

package net.jinglong.demo1;

import java.text.SimpleDateFormat;
import java.util.Date;

public class PlugIn {
    private String time;
    private String timeFormat;

    public String getTime() {
        if (timeFormat != null) {
            SimpleDateFormat df = new SimpleDateFormat(timeFormat);     //设置日期格式
            System.out.println(df.format(new Date()));                  //new Date()为获取当前系统时间
            time = df.format(new Date());
        }else {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");     //设置日期格式
            System.out.println(df.format(new Date()));                  //new Date()为获取当前系统时间
            time = df.format(new Date());
        }
        return time;
    }

    public void setTimeFormat(String timeFormat) {
        this.timeFormat = timeFormat;
    }

    public String getTimeFormat() {
        return timeFormat;
    }
}

调用入口

package net.jinglong.demo1;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Demo {

    public static void main(String[] args) throws Exception {
        //获取PlugIn的Class对象
        //1、通过Class.forName()方法加载字符串,就可以得到该字符串做代表的Class对象
        Class<?> clazz = Class.forName("net.jinglong.demo1.PlugIn");

        //获取该类中的所有属性
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
            System.out.println("修饰符:" + Modifier.toString(field.getModifiers()));
            System.out.println("类型:" + field.getType());
            System.out.println("属性名:" + field.getName());

        }

        //获取该类中的所有方法
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
// 			System.out.println(method);
//			System.out.println("修饰符:" + Modifier.toString(method.getModifiers()));
//		    System.out.println("方法名:" + method.getName());
//		    System.out.println("返回类型:" + method.getReturnType());
            Class<?>[] clazzes = method.getParameterTypes();
            for (Class<?> class1 : clazzes) {
//				System.out.println("参数类型:" + class1);
            }
        }

        //通过Class对象创建对象
        PlugIn plugIn = (PlugIn) clazz.newInstance();

        //获取属性名为timeFormat的字段对象,重新设置值
        Field timeFormat = clazz.getDeclaredField("timeFormat");
        //字段属性为private,设置为可以访问
        timeFormat.setAccessible(true);
        //设置timeFormat的值
        timeFormat.set(plugIn, "yyyy-MM-dd");


        //通过Class对象获取名为getTime、无参数类型的方法对象
        Method empty = clazz.getDeclaredMethod("getTime");
        //方法属性为private,设置为可以访问
        empty.setAccessible(true);
        //调用empty()方法
        empty.invoke(plugIn);
    }

}

显示结果

private java.lang.String net.jinglong.demo1.PlugIn.time
修饰符:private
类型:class java.lang.String
属性名:time
private java.lang.String net.jinglong.demo1.PlugIn.timeFormat
修饰符:private
类型:class java.lang.String
属性名:timeFormat
2019-11-19 20:28:25

当禁调timeFormat写入代码块,调用结果如下

private java.lang.String net.jinglong.demo1.PlugIn.time
修饰符:private
类型:class java.lang.String
属性名:time
private java.lang.String net.jinglong.demo1.PlugIn.timeFormat
修饰符:private
类型:class java.lang.String
属性名:timeFormat
2019-11-19 20:32:07