Java反射机制

一、简介

百度百科: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

当禁调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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值