这篇文章我们来讲一下java的代理与反射,这是很重要的一部分内容。

目录

1.什么是反射

2.获取class对象的三种方式

3.反射获取构造方法

4.利用反射来获取成员变量

5.利用反射来获取成员方法

6.反射的作用

7.反射小结


1.什么是反射

首先,我们来看一下什么是反射

官方定义:反射允许对封装类的字段,方法和构造函数的信息进行编程访问

解释:反射允许对成员变量成员方法构造方法的信息进行编程访问

说人话:就是反射可以把类里面的所有信息都获取出来,并对获取出来的信息进行操作

反射的用处举例:

idea里面的自动提示功能:

idea中的方法参数提示功能(快捷键:Ctrl+P):

问:从类里面拿东西,IO流也行,为什么要用反射呢?

答:IO流无法判断类的构造函数和普通方法,无法判断同名的成员变量和方法中的变量。

反射要学习的内容:

2.获取class对象的三种方式

获取class对象有三种方式

  • Class.forName(“全类名”)
  • 类名.class
  • 对象.getClass()

注意:我们通过反射获取的不是.java文件,获取的是.class字节码文件,然后我们在.class字节码文件中找到类的相应信息,然后对这些信息进行操作

下面,我们来看一下一个类的三个阶段

解析:首先,我们编写一个.java文件,然后它会被JVM编译成.class文件,这个阶段是在硬盘中实现的,这个阶段也称为源代码阶段。然后,我们运行程序,.class被拿到内存中加载,这个阶段是加载阶段,然后,我们创建对象,计算机就会在内存中创建出类的实例化对象,这个阶段就是运行阶段。其中,这三个阶段分别对应了上面反射获取类的三种方式

下面,用代码来具体的演示一下这三种方式:

有一个疑问,它为什么是true?首先,我要明白我们通过反射获取的是什么?我们获取的是类的.class字节码文件,我们获取它干啥?我们通过获取这个类的字节码文件然后分析然后来获取类的信息,所以,我们通过反射最终获取的是类的信息,因为这是同一个类,所以它的信息是一样的,所以是true!

3.反射获取构造方法

上面,我们讲了如何获取类的字节码文件,现在,我们来讲一下如果在类的字节码文件中获取类的构造方法信息。

我们知道,java的思想是万物皆对象,我们通过反射获取类的字节码文件,那么就用Class类对象来接收它,我们获取类的构造方法,那就通过Constructor类对象来接收它,我们获取类的字段(成员变量),那就通过Field类对象来接收它,我们获取类的成员方法,那就通过Method类对象来接收它。

下面,我们来看一下用反射获取类的构造方法的方法:

(这些方法的格式和javaAPI的格式是一样的,可以按照那个的格式来理解)

下面通过具体实例来看一下里面的一些方法的使用:

然后看一下运行结果:

再看一下利用构造方法中的类来创建对象:

结果:

注意:我们在调用这些方法的时候,它获取的内容或受到权限修饰符的限制,也就是说,当我们用不同的方法虽然获取的都是构造方法,但是构造方法的权限修饰符不一样,而导致最终的结果也会不一样。并且,我们用这些构造方法的对象中的类来创建对象时,也会受到权限修饰符的影响,甚至受到形参的影响,但是这些都是小问题,我们在具体运用时是可以自己解决的,所以我上面就没有演示那些问题的案例。

4.利用反射来获取成员变量

上面已经具体的讲过了反射获取类信息的本质,所以这里就不多说了。

下面,我们来看一下利用反射来获取成员变量的方法:

下面通过具体案例来演示一下:

看一下结果:

再用它来创建对象看一下:

还是要注意权限修饰符

5.利用反射来获取成员方法

下面,我们来看一下利用反射来获取成员方法的方法:

下面,还是来看一下具体实例吧

结果:

6.反射的作用

反射的作用主要有以下两点:

  1. 获取一个类里面所有的信息,获取到了之后,再执行其他的业务逻辑
  2. 结合配置文件,动态的创建对象并调用方法

下面通过具体的代码案例来演示下反射的这两个作用

案例一:对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去

代码如下:

结果如下:

案例二:反射可以跟配置文件结合的方式,动态的创建对象,并调用方法

代码如下:

运行结果:

7.反射小结

下面来小结一下反射(自己的理解)

首先,我们要区分类和对象,类是模板,对象是类的实例化。我们反射获取的是类的.class文件,不是对象。我们知道java有.java文件(就是我们自己写的)和.class字节码文件(JVM编译的),我们反射获取的是类的.class字节码文件,我们获取到它后就可以分析解剖它,说白了就是获取类的所有信息,于是,我们可以通过反射来获取类的成员变量,成员方法,构造方法(实际上是从类的.class字节码文件中获取的)。而java又是面向对象的,所以我们获取出来这些信息后,又把这些信息全部封装到类中,于是有了Constructor,Field,Method类有了这些类我们就可以创建这些类的对象,然后通过对象和类里面的方法,就可以把那些信息给拿出来了。注意,我们通过获取.class字节码文件然后获取类的那些信息,我们是直接拿不出来的,那些信息都被封装在类里面。因为我们有了这些类的对象,而这些对象里面都是可以操作我们手写类的方法,所以我们就可以通过这些类的对象来创建我们手写类的对象了。就比如,我们有了Constructor类对象,它是我们构造方法类对象,所以呢我们就可以通过这个对象来操作我们的手写类的构造方法,然后就创建出对象了。Field类对象也一样,我们有一个手写类对象,我们把这个类对象传进去,然后调用Field类对象方法,就可以修改对象的成员变量值了。Method的类对象的逻辑也是一样的。这上面就是反射的基本逻辑。但是有些细节我们需要注意:比如说权限修饰符的问题,比如说方法的重载,这些都是细节问题,都需要注意!