Java基础--反射机制的知识点梳理

小编 2026-07-14 阅读:1182 评论:0
什么是反射?  正常编译执行java文件时,会生成一个.class文件,反射就是一个反编译的过程...

什么是反射?

  正常编译执行java文件时,会生成一个.class文件,反射就是一个反编译的过程,它可以通过.class文件得到一个java对象.一个类会有很多组成部分,比如成员变量,成员方法,构造方法等,反射可以通过加载类,解剖出类的各个组成部分.

为什么要用反射?

  我们需要访问一个类的方法或字段的时候,直接new一个该类的对象然后调用就好了,干嘛要用反射呢,刚学的时候我也不懂,并且学了也没机会用到,或者根本用不到,后来开始接触strut2,hibernate等一些框架的时候,才慢慢懂得了一点反射的强大之处,在框架中会有很多配置文件,而配置文件中一般只有一些类的全路径的字符串,而就是通过这些个字符串,就能得到这个类的对象,以及类中所有的信息.我给你这个类,当然你可以轻松得到它的实例,但如果我给你的只是这个类的路径的字符串呢?没有反射你就傻眼了吧.学习反射一般只会在写框架的时候用到,如果你没有到达写框架的高度,能够看懂别人的框架也是极好的.

这里面还涉及到一个静态编译和动态编译的概念,前者的意思就是在编译的时候已经绑定了对象,确定了对象,而动态编译就是知道运行的时候,才根据需要去绑定对象.

加载类:

  加载类就是获得类的字节码,要想通过反射获取到一个类的内部信息,首先得先获取到这个类的字节码对象.

  加载类有三种方式:

现在我有一个类User,我希望加载这个类,获得它的字节码对象:

package com.wang.reflect;public class Demo01 {    public static void main(String[] args) throws ClassNotFoundException {                //第一种方式   通过Class的forName方法,注意使用目标类的全路径        Class clazz=Class.forName("com.wang.reflect.User");                //第二种方式 通过Object类的getClass()方法        Class clazz1=new User().getClass();                //第三种方式  通过类的.class属性        Class clazz2=User.class;    }}

  一般第一种方式最常用,也最好用,因为看代码我们可以发现,后两种在编译前就必须要知道具体的类的,否则就无法通过编译,而第一种方式,没有那么大的强制性,他只是提供了一个空间,运行时你可以想把谁传给它就把谁传给它,这个类甚至可以不存在,后果只是抛出一个异常.

 

反射类的构造函数(Constructior):

  获得了Class对象以后就可以调用class的很多方法了,比如getConstructor(..),方法就可以获得构造器的对象.下面分别通过获取User类的无参和带参构造器,进而得到该类对象的例子,感受一下反射技术.

public class User {    private String name;        public User(){        System.out.println("无参构造函数");    }        public User(String name){        this.name=name;        System.out.println("带一个参数的构造函数:::"+name);    }}//-----------------------------------------------------------------------------@Test    public void test01() throws Exception{        //通过Class的forName方法,注意使用目标类的全路径        Class clazz=Class.forName("com.wang.reflect.User");                //通过无参构造器得到该类对象,        Constructor c=clazz.getConstructor(null);        User user=(User) c.newInstance(null);                //通过带参构造器获得该类对象        Constructor c1=clazz.getConstructor(String.class);        User user1=(User)c1.newInstance("nick");    }

注意.在通过无参构造函数获得对象时,还可以直接调用User user=(User)clazz.newInstance();得到,内部的原理也是先调用了无参构造器,如上.注意,使用"newInstance"方法只能调用类的无参构造方法,这个操作实际相当于使用了new进行对象实例化.

 

反射类的方法(Method):

  一个类中总会有实现某些功能的方法,这些方法可能有返回值也可能没有返回值,可能有参数也可能没参数,可能是静态方法也可能是普通方法.下面通过例子分别讲解:

package com.wang.reflect;public class User {    private String name;        public User(){        System.out.println("无参构造函数");    }        public User(String name){        this.name=name;        System.out.println("带一个参数的构造函数:::"+name);    }    //1无参无返回值的方法login    public void login(){                System.out.println("用户登陆了");    }    //2带参有返回值的方法eat    public String eat(String name){        System.out.println("name"+"去吃饭去了");        return "eat";    }    //3带参无返回值的静态方法    public static void sleep(String name){        System.out.println(name +"去睡觉了");    }}//-----------------------------------------------------------------@Test    public void test02() throws Exception{        User u=new User();            //通过Class的forName方法,注意使用目标类的全路径        Class clazz=Class.forName("com.wang.reflect.User");            //1获取无参无返回值的方法login        //获得一个方法名为"login"但是没有参数的Method对象        Method method=clazz.getMethod("login", null);        //第一个参数:要想执行这个login方法你总得告诉她是哪个User的login方法吧,第二个参数就是login方法的参数,这里为null        method.invoke(u, null);    //2获取有参有返回值的方法eat        Method method1=clazz.getMethod("eat", String.class);        String agrs=(String)method1.invoke(u, "超人");    //3获取带参无返回值的静态方法sleep,
     //静态方法 可以不提供User对象,传一个null即可
Method method2=clazz.getMethod("sleep", String.class); method2.invoke(null, "蝙蝠侠"); }

//执行之后打印结果为:

无参构造函数
用户登陆了
超人去吃饭去了
蝙蝠侠去睡觉了

反射类的字段:

@Test    public void test03() throws Exception{        User u=new User();        u.setName("钢铁侠");        //通过Class的forName方法,注意使用目标类的全路径        Class clazz=Class.forName("com.wang.reflect.User");        //注意需要用getDeclareField方法,getField只能获取到public的字段        Field f=clazz.getDeclaredField("name");        f.setAccessible(true);        String name=(String)f.get(u);        System.out.println(name);    }

 

 

 

 下面介绍一个使用反射的简单例子:

package com.wang.reflect;import java.lang.annotation.Annotation;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.util.ResourceBundle;interface Person {    public void location(String location);}class Student implements Person{    @Override    public void location(String location) {            System.out.println("学生的工作地点是"+location);    }    }class Teacher implements Person{    @Override    public void location(String location) {        System.out.println("老师的工作地点是"+location);    }    }class Factory{    public static Person getInstance(String str) throws Exception, IllegalAccessException, ClassNotFoundException{        Person person=(Person)Class.forName(str).newInstance();        return person;    }}public class TestReflect {    public static void main(String[] args) throws Exception {        //Person p=(Person)Class.forName("com.wang.reflect.Student").newInstance();        //p.location("学校");        Person p=Factory.getInstance("com.wang.reflect.Teacher");        p.location("学校");        }}

这个例子使用了简单的工厂模式,调用person的location方法,通过反射,实际应用中并不会出现这样的代码,这里只是做一个反射的运用的演示.在测试代码中,只要简单的修改ForName方法中的字符串,就可以调用相应的方法.

 

版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
标签列表