Javaweb的学习02_反射

反射

反射:框架设计的灵魂

      框架:半成品软件。可以在框架的基础上进行软件的开发,来简化编码

      反射的概念:将 类的各个组成部分 封装为其他对象,这就是反射机制

Java代码 在计算机中经历的三个阶段:

      Source源代码阶段、Class类对象阶段、Runtime运行时阶段

Class类对象阶段:

把成员变量封装为Field对象    Field[ ]fields    ,

把构造方法封装为Constructor对象    Constructor[ ]cons    ,

把成员方法封装为Method对象     Method[ ]methods     。      这就是反射机制

反射的好处:

        1.可以在程序运行过程中 操作这些对象

        2.可以解耦,降低程序的一些耦合性和紧密的联系程度,来提高程序的可扩展性

获取Class对象的方式:(共三个方式,和三个阶段相对应)

        1. Class.forName("全类名")  :将字节码文件加载进内存,返回Class对象
        2. 类名.class  : 通过类名的属性class获取
        3. 对象.getClass()  : getClass()方法在object类中定义着

注:object类是所有类的父类

示例(获取Class对象)如下:

 先定义两个成员变量:

可得到这两个参数的构造:

空参的构造:

然后把两个的Getter和Setter也弄出来

(setter是一种更新变量值的方法。Getter是一种读取变量值的方法)

最后再定义一个toString方法:

(使用Ctrl键可以同时选中两个)

那么这个Person.java类 就写完了,即字节码文件就有了

反射reflect范例:

Class.forName返回与给定的字符串名称相关联 类 或接口 的Class对象
Class.forName是一个静态方法

全类名 就是 包名.类名

出现编译异常,把它直接抛出去即可:

返回一个class对象

注意 这里起名的时候就不要起class了,因为它是一个定义类的关键字

运行主方法,可以发现运行成功:

运行这三种方式,结果显示 三个字符串的表示形式都是一样的(但不能直接说明这三个对象是一样的,要进行判断)

这三个对象对应的都是Person这个字节码文件在内存里面生成的Class类对象

可以用==来比较三个对象,来判断这三个对象是否是一样的(==比较的是对象的内存地址

(如果地址值相同,则为同一个对象;反之,这三个对象是不一样的)

结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象 都是同一个

  每一个字节码文件 对应的Class类对象 都不相同

获取Class对象的方式:

        1. Class.forName("全类名")  :将字节码文件加载进内存,返回Class对象

        //多用于配置文件,将类名 定义在配置文件中。 读取文件,加载类

       

        2. 类名.class  : 通过类名的属性class获取

        //多用于参数的传递

        3. 对象.getClass()  : getClass()方法在object类中定义着

        //多用于对象的获取字节码的方式

Class对象的功能:

       获取功能:
            1.获取成员变量们

                    Field[ ]  getFields( )   :获取所有public修饰的成员变量

                    Field getField(String name)  :获取指定名称的public修饰的成员变量

                    Field[ ]  getDeclaredFields( )  :获取所有的成员变量,不考虑访问权限修饰符

                                                                   (在反射面前,甚至是私有的private也可以被访问)

                    Field  getDeclaredField(String name)

            2.获取构造方法们

                    Constructor<?>[ ]  getConstructors( )

                    Constructor<T>  getConstructor(类<?>... parameterTypes)

                    Constructor<?>[ ]  getDeclaredConstructors( )

                    Constructor<T>  getDeclaredConstructor(类<?>... parameterTypes)

            3.获取成员方法们

                    Method[ ]  getMethods( )

                    Method  getMethod(String name, 类<?>... parameterTypes)

                    Method[ ]  getDeclaredMethods( )

                    Method  getDeclaredMethod(String name, 类<?>... parameterTypes)

            4.获取类名

                    String getName( )

补充:1.(快捷键) psvm,可快捷生成main方法

Enter键 回车

2.(快捷键)iter ,生成高效for循环

3.(快捷键)sout ,自动补全System.out.println();

4.ieda-自动引入局部变量(introduce local variable)快捷键

   ctrl+alt+V        自动创建一个对象类型和对象名

Field:成员变量

      操作:

             1.设置值 
                   void set(Object obj, Object value)

(没有显示出来,可能是因为没有重新去修改toString方法,需要去重新生成一下)

             2.获取值
                   get(Object obj)

                   注意:传的是对象,所以括号里的是一个对象

             3.忽略访问权限修饰符的安全检查
                        setAccessible(true)   

                  暴力反射(不管是Field对象还是Constructor、Method 对象 里面都有这一方法)

 上图出现了ILLegal....非法的访问异常, 所以在使用一些不是由访问权限修饰符public修饰的成员的时候,在访问之前,需要以下这行代码来 忽略访问权限修饰符的安全检查(即暴力反射)

             .setAccessible(true);

Consructor :构造方法

         创建对象:
               T newInstance(Object... initargs)

  参数initargs:表示通过构造方法创建对象时 传递的实际参数

(使用此 Constructor对象 表示的构造函数,使用指定的初始化参数 来创建和初始化 构造函数的声明类的新实例.)

              如果使用 空参数 构造方法 创建对象,操作可以简化 :使用Class对象的newInstance方法

补充:       当使用Declared时 仍然要使用到 暴力反射: constructor1.setAccessible(true);

Method :方法对象

         执行方法:
                Object invoke(Object obj, Object...args)
         获取方法名称:
                String getName

获取功能的示例如下:

 

反射的案例:

        需求:写一个“框架”,不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法

             实现这个需求需要借助两个技术:

                   1.配置文件

                   2.反射

             步骤:
                   1.将需要创建的对象的全类名 和 需要执行的方法 定义在配置文件中
                   2.在程序中加载读取配置文件
                   3.使用反射技术来加载类文件进内存
                   4.创建对象
                   5.执行方法

已有两个方法,一个是Person.java中的eat方法

另一个是Student.java中的sleep方法

在src里创建一个New的(file)文件

或者

第一个执行结果如下:

第二个结果如下:

注:

1.类加载器classLoader

2.如果写一个类需要动态的获取某个文件的位置,从而能够获取此文件的资源,可以使用Class.getResourceAsStream()方法,可以看到它最终返回了一个输入流,也就是返回一个InputStream对象方便对此文件资源通过IO流进行获取

3.Class.forName返回与给定的字符串名称相关联 类 或接口 的Class对象
Class.forName是一个静态方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值