ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

关于反射机制的个人理解

2021-09-11 17:02:26  阅读:140  来源: 互联网

标签:反射 Apple 实例 clazz 获取 理解 机制 Class


一、什么是反射?

用光的反射来说明,光在遇到玻璃、水面等其他介质的时候,在分界面上又返回原来物质的一种现象。

二、应用场景

在Java的业务开发中,平常很少用到反射原理,也就不怎么接触到反射机制。但是,因为反射我们才能使用各种框架。例如Spring/Spring Boot 、MyBatis等许多框架中都用到了反射机制。

三、优点和缺点

优点:能够让代码更加的灵活,同时也为各种框架提供了便利。
缺点:我们都知道Java 的特性包括封装,恰巧反射机制就破坏了这种封装机制。同时也增加了一些安全问题。同时,反射的性能也稍微的差一点。不过在框架中这种性能差异显得微乎其微。

四、反射示例

4.1、获取Class对象的方式

通过前面的说明,我们知道一定要通过一种介质才能得到想要的对象。而这个介质就是Class类。
根据官网文档的解释,Class 类的实例表示正在运行的 Java 应用程序中的类和接口。Class 类的实例表示正在运行的 Java 应用程序中的类和接口。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

4.1.1 知道具体类

Class clazz = TargetClass.class ;

我们已知一个类,通过.class这种方式就能获取到对应的Class实例。
但是我们一般是不知道具体的类,通过遍历包下面的类来获取对象,通过此方式获取的Class对象不会进行初始化。

4.1.2 通过Class.forName()传入类的路径

Class clazz = Class.forName(" com.test.TargetClass");

例如在Jdbc的连接中,我们要获取驱动,一般就用这种方式来获取相应的Class实例。

4.1.3 通过对象实例instance.getClass()获取

TargetClass object = new TargetClass();
Class clazz = object.getClass();

4.1.4 通过类加载器传入路径

ClassLoader loader = ClassLoader.getSystemClassLoader();
Class clazz = loader.loadClass("com.base.TargetClass");

通过类加载器加载一个类获取Class对象时不会进行初始化。也就意味着构造方法和类初始化器都不会被执行。只有new对象时,这些才会执行。

五、反射的基本操作

5.1、创建一个用来反射操作的类。

public class Apple {

    private String name ;

    public Apple(){
        name = "苹果";
    }

    public void show( String s ){
        System.out.println( "我最喜欢:" + s );
    }

    private void otherShow(){
        System.out.println( "我是:" + name );
    }
}

5.2 使用反射

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

public class ReflectApple {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        //这是通过前面的四种方式来获取Apple的Class实例
        Class<?> clazz = Apple.class;
        Class<?> clazz2 = Class.forName("com.base.Apple");
        Apple apple1 = new Apple();
        Class<?> clazz3 = apple1.getClass();
        ClassLoader loader = ClassLoader.getSystemClassLoader();
        Class<?> clazz4 = loader.loadClass("com.base.Apple");

        //我们用第一个Class实例获取要操作的类
        Apple apple = (Apple)clazz.newInstance();

        /**
         * 用第二个Class实例获取类中的方法,修饰符为public的方法
         * 返回一个包含某些 Method 对象的数组
         * 如果此 Class 对象表示没有公共成员方法的类或接口,或者表示一个基本类型或 void,则此方法返回长度为 0 的数组。
         */
        Method[] methods = clazz2.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        /**
         * 用第三个Class实例获取类中的字段,由于是private,所以数组的长度为0
         * 返回一个包含某些 Field 对象的数组
         */
        Field[] fields = clazz3.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
        //获取指定的方法,同时传入参数类型
        Method showMethod = clazz4.getDeclaredMethod("show" , String.class );
        //调用方法,并传参
        showMethod.invoke( apple , "水果");

        Field field = clazz.getDeclaredField("name");
        //为了对其中类的私有字段进行修改,这里取消安全检查
        //值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
        field.setAccessible( true );
        field.set( apple , "柠檬");

        //指定获取私有方法
        Method otherShowMethod = clazz.getDeclaredMethod("otherShow" );
        otherShowMethod.setAccessible( true );
        otherShowMethod.invoke( apple );
    }
}

输出的内容如下
show
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
我最喜欢:水果
我是:柠檬

如输出的结果所示,这里的show方法是我们自己定义的。其他的方法则是继承Object
在遍历方法的时候,并不会获取到私有方法,所以遍历时并不会显示otherShow 这个方法。
注意getDeclaredMethod获取指定方法的时候,如果要操作的方法中带有参数,则要加入相应的参数类型Class实例。

以上内容是参考了书集和官方文档以及自己测试结果所写,全部为个人理解。如果有错误请批评指正。
转载请注明出处,谢谢。

标签:反射,Apple,实例,clazz,获取,理解,机制,Class
来源: https://www.cnblogs.com/lemon-java/p/15255686.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有