Java中什么是反射,反射的用法

本文阅读 8 分钟
首页 代码,Java 正文

反射是啥?

反射既然有“反”,就说明它是一个逆向的过程。那我们先来看看正向过程是怎样的。

首先写一个实体类,new出该类的对象,然后调用属性、方法实现一些功能。 //没有反射时,new对象以及调用对象的属性以及方法

// An highlighted block
public void Test1(){ 
    //实例化对象
    Person person=new Person();
    //调用属性
    person.setAge(18);
    //调用方法
    person.show();
}

以上是我们不使用反射时创建对象,运用对象的用法,那到底什么是反射呢?反射的用法是啥? img 我们可以看到,之前我们所运行的程序都是在编译时就已经链接了所有所需的类,也就是说程序运行的时候,项目所需要的类都已经加载好了,而反射则不是这样,它允许程序在运行的时候再加载、探知、使用那些在编译时未知的类,它是逆着来的。大概也可以这样理解,就是在程序加载运行的时候,同时再加载、使用一些未知的类,这两个操作是同时运行的。加载这些未知的类时,也可以通过一些方法得到这些类的相关信息

类比一个现实生活中的例子 <font face="宋体" color="gray" size="3"> 1,姐妹,你见我的修眉刀没? 2,我昨天放粉饼的时候,好像在化妆桌的小抽屉里看到了,你去找找看看吧 3,好的 </font> 然后你从“粉饼”推出了“化妆桌的小抽屉”,然后找到了“修眉刀” 其实我们的反射也是这样的,在不知道类信息的时候,从类或者对象中推导出Class类型,然后再从Class中获取类的一些相关信息

这样我们也就知道了,要想拿到类的相关信息,第一步就需要先拿到Class类。

先说说什么是Class类

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。也就是说Class类是以上这些数据类型的类,也可以理解为是他们的“爷爷”。 假如现在有一个Person类,Person类的实例对象是person,现在要通过Person类或者实例person拿到Class,然后再通过Class获取Person类的一些相关信息,比如方法名,修饰符、属性、方法、构造函数等等

反射的使用过程

          找到化妆桌小抽屉------获取Class类

知道了什么是Class类之后,我们就来说说怎么才能获取Class类

获取Class类有3种方式:

// An highlighted block
//获取person的Class类型,每个类型都有一个Class类型
        //方式一,知道类的实例时,用实例获取
        Person person = new Person();
        Class c1=person.getClass();
        //方式二,不知道实例时,用类名称获取
        Class c2=Person.class;
        //方式三,没有类名,也没有实例名,用Class的forname()方法获取
        Class c3;

        { 
            try { 
                c3 = Class.forName("cn.entity.Person");
            } catch (ClassNotFoundException e) { 
                e.printStackTrace();
            }
        }
        System.out.println(c1.hashCode());//通过打印他们的hashcode值来判断拿到的Class是不是同一个
        System.out.println(c2.hashCode());
        System.out.println(c2.hashCode());

这样就可以获取到Person的Class类了,现在已知条件有:Person类,Class类,以及c1。 在这里想说一下,c1、c2、c3叫做Person的“类类型”           找到修眉刀------获取Person类的相关信息

应用一:获取Person类的基本信息 img

//获取person的Class类型,每个类型都有一个Class类型
        //方式一,用实例获取
        Person person = new Person();
        Class c1=person.getClass();
        System.out.println("名称是:"+c1.getName());
        System.out.println("简称是:"+c1.getSimpleName());
        System.out.println("修饰符是:"+c1.getModifiers());
        System.out.println("所包含的所有内部类:"+c1.getDeclaredClasses());
        System.out.println("所在的外部类:"+c1.getDeclaringClass());

运行之后的结果: img 应用二:获取Person类的属性 img

//先获取Class类型
        Person person=new Person();
        Class c1=person.getClass();//类类型
        //使用getField()方法,只能访问修饰符为public
        System.out.println("---------getField()-----------");
        Field name=c1.getField("message");
        int modifiers = name.getModifiers();
        System.out.println("名字是:"+name.getName());
        System.out.println("类型是:"+name.getType());
        System.out.println("访问修饰符:"+ Modifier.toString(modifiers));

        //使用getFields()方法,只能访问修饰符为public
        System.out.println("---------getFields()-----------");
        for (Field field : c1.getFields()) { 
            System.out.println("名字是:"+field.getName());
            System.out.println("类型是:"+field.getType());
            int m=field.getModifiers();
            System.out.println("访问修饰符:"+ Modifier.toString(m));
        }

        //使用getDeclaredFields()方法,不限制访问修饰权限
        System.out.println("---------getDeclaredFields()-----------");
        for (Field d : c1.getDeclaredFields()) { 
            System.out.println("名字是:"+d.getName());
            System.out.println("类型是:"+d.getType());
            int m=d.getModifiers();
            System.out.println("访问修饰符:"+ Modifier.toString(m));
        }

运行之后的结果: img 应用三:获取Person类的方法 img

System.out.println("=========方法展示=========");
        //获取Class类类型
        Class c1= Person.class;
        for (Method m : c1.getDeclaredMethods()) { 
            System.out.println("方法名:"+m.getName());
            System.out.println("返回值类型是:"+m.getReturnType());
            Class[] types = m.getParameterTypes();
            System.out.print("该方法");
            if(types.length==0){ 
                System.out.println("没有参数列表");
            }else{ 
                for (Class c:types) { 
                    System.out.print("的参数列表是:"+c.getSimpleName());
                }
            }
            int xiu=m.getModifiers();
            System.out.println("修饰符是:"+ Modifier.toString(xiu));
            //获取方法所属的类
            Class shi=m.getDeclaringClass();
            System.out.println("方法声明在:"+shi.getName()+"中");
            for (Class e : m.getExceptionTypes()) { 
                if(e!=null){ 
                    System.out.print("该方法抛出的异常有:");
                    System.out.println(e.getName()+",");
                }

            }
            System.out.println("");
        }

运行之后的结果: img 应用四:获取Person类的构造方法 img

System.out.println("============构造方法展示============");
        Class c1=Class.forName("cn.entity.Person");
        Constructor[] cs=c1.getDeclaredConstructors();
        for(int i=0;i<cs.length;i++){ 
            int xiu=cs[i].getModifiers();
            System.out.println("访问修饰符:"+ Modifier.toString(xiu));
            Class[] params=cs[i].getParameterTypes();
            if(params.length==0){ 
                System.out.println("该方法没有参数");
            }else{ 
                System.out.print("该方法的参数列表为:");
                for (Class p:params) { 
                    System.out.print(p.getSimpleName()+"\t");
                }
            }
            System.out.println();
            System.out.println("-----------------------");
        }

运行之后的结果: img 以上只是对个别功能的列举,更具体的可以去API文档中寻找: 点击查看API 好了,最后我们再总结一下反射的概念: Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,这种动态获取、调用对象方法的功能称为java语言的反射机制。

反射存在的必要性?

“反射机制是很多java框架的基石”。(暂时我也不是很懂,只是看一些资料是这么说的) (1)在xml文件或者properties里面写好了配置,然后在Java类里面解析xml或properties里面的内容,得到一个字符串,然后用反射机制,根据这个字符串获得某个类的Class实例,这样就可以动态配置一些东西,不用每一次都要在代码里面去new或者做其他的事情,以后要改的话直接改配置文件,代码维护起来就很方便了。 (2)有时候要适应某些需求,Java类里面不一定能直接调用另外的方法,这时候也可以通过反射机制来实现。

反射的缺点

我们在代码中也能看到,反射的代码比正常调用的代码更多,性能也慢,所以应避免使用反射。这就相当于如果你本来就知道修眉刀在哪,就没必要再通过粉饼——化妆桌小抽屉——修眉刀这条路了。

是否使用反射的标准是啥?

如果一个功能可以不用反射完成,那么最好就不用。

本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://blog.csdn.net/qq_46540738/article/details/112498162
-- 展开阅读全文 --
安全面试之XSS(跨站脚本攻击)
« 上一篇 07-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复