Spring前瞻----Java反射机制

导言:
java反射机制核心是一种在程序运行时动态加载类并获取详细信息,从而操作类的对象的属性和方法。


一、什么是反射

从专业角度来说:

Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性遂行调用。我们杷这种动念获取对象信息和调用对象方法的功能称之为反射机制。反射其实是获取类的字节码文件,也就是.class文件,我们可以通过Class类的对象进行获取。注:获取字节码文件需要JVM的操作。

关于Class类:

Class类的实例表示正在运行的Java应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象(包括基本数据类型)
Class类没有公共构造方法。Class对象是在加我类时由Java虚拟机以及通过调用类加我器中的defineClass方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。注意在运行期间,一个类只有一个Class对象产生。

具体过程如图示:

通俗点来说,反射机制可以看做游戏常见的不停服更新,在程序仍旧在运行的时候仍然可以修改查看内容。


二、反射机制的优缺点

优点

在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。

缺点

(1)反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。


三、直观感受到的用处

反射机制其实在我们日常编译的过程中能经常用到,也许之前你并不知道,但是现在你可以有一个更深层次的认识了。
在编译中使用到的反射技术如:

(1)使用编译器如IDE,Eclipse等编码时,当输入一个对象或类,自动跳出他的属性,方法,这其实运用到了反射技术。
(2)开发各种通用框架,如Spring,需要根据配置文件加载不同的类或对象调用不同类和方法,这必须用到反射,运行程序时动态加载需要加载的对象。
(3)加载数据库驱动时,用到的也是反射机制(Class.forName("com.mysql.jdbc.Driver");)
...

由此看来,反射技术其实在日常的编码中很常见,特别是框架中,称为框架的灵魂也不为过。


四、具体运用

实践出真知,来上段代码感受下

来,让我们先创建一个类firstGrade和类studentClass,创建变量的get和set方法(为了便捷就没有写出)

    private String zhangSan;
    private int zhangSanAge;
    private String liSi;
    private int liSiAge;
    public studentClass(String zhangSan,int zhangSanAge,String liSi,int liSiAge){
        this.zhangSan=zhangSan;
        this.zhangSanAge=zhangSanAge;
        this.liSi=liSi;
        this.liSiAge=liSiAge;
    }

然后,让我们创建实现的方法

public String toString() {
        return "张三职位:" + zhangSan  +
                "年龄:" + zhangSanAge +
                "李四职位:" + liSi +
                "年龄:" + liSiAge ;
    }

    public void rollCall(){
        System.out.println("张三职位:"+zhangSan+"年龄:"+zhangSanAge+"李四职位:"+liSi+"年龄:"+liSiAge);
    }

重点来了,通过方法让其实现反射机制(具体看注释)

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        //加载类,指定类的完全限定名:包名+类名
        Class stClass = Class.forName("School.studentClass");
        //此时,发现值和字节码中类名称一致
        System.out.println(stClass);

        //解刨(反射)类stClass的公开构造函数
        Constructor cons = stClass.getConstructor(String.class,int.class,String.class,int.class);

        //调用构造方法,并向其输入值
        Object obj=cons.newInstance("班长",19,"学习委员",18);
        //注意,此时是共有方法
        System.out.println(obj.toString());

        //暴力反射,解除私有设置
        /*注意:getField 只能获取public的,包括从父类继承来的字段
        *   getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。
        * 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上setAccessible(true)
        * */
        Field f= stClass.getDeclaredField("zhangSanAge");
        f.setAccessible(true);
        f.set(obj,20);

        //该方法的第一个参数name是要获得方法的名字,第二个参数parameterTypes是按声明顺序标识该方法形参类型。
        //因为answer没有形参,所以为null
        Method m=stClass.getMethod("rollCall",null);
        //通过invoke方法执行,invoke需要两个参数一个是类的实例,一个是方法参数。
        m.invoke(obj,null);
    }

细心地你肯定发现了,由于破除了私有限制,所以导致代码不安全了,这也是反射机制的一个缺点。


以上就是java反射机制的简单介绍,如有错误,麻烦指出,感谢耐心到现在的朋友:) ---By 不断努力的Yang

posted @ 2021-03-14 20:16  Lachlan_Yang  阅读(141)  评论(0编辑  收藏  举报