前言
写这篇文章是因为在阅读源码时,发现在源码中总会应用到反射和泛型,所以经过学习后,总结如下。有不对或者遗漏的地方,也欢迎大家留言指正和讨论。废话不多说,开始整活儿。
一、反射
1.什么是反射?
在讲反射之前,我们先简单说一下jvm类加载的过程。
源代码 – 类编译器将源码编译为class文件 – 类加载器(classLoader)将class文件加载到jvm中
(因为这篇文章重点是反射和泛型,所以这里只是简单概括,后续肯定会写关于JVM的文章,在那里再详细介绍 ,要是觉得这篇写的还行,可以先关注上,大家一起成长,笔芯。)
class文件中包含了一些重要信息,比如类的属性、方法、实现的接口和父类等等。其中包括构造函数、方法和字段等部分内容也是我们反射所需要的。
可能看到这里,大家觉得有点云里雾里,接下来我们看一张图,上面可以看到类加载的区别。
这张图大家可以明显看出这两种加载方式主要区别就在于什么时候操作class文件。反射是在运行期对class文件进行操作。可能这么说还是有点抽象,大家再看下一张图,通过大家熟悉的代码来了解。
看完上面这张图,相信大家聪明的小脑袋瓜已经开始懂了。正常我们new一个对象的过程就是在编译期加载对象.class文件然后在class文件中查找构造函数,再通过构造函数创建对象。是不是似曾相识,是的,就是上面我们刚看到的内容。而反射呢,是在运行期加载class文件,然后再由我们自己创建构造函数,以此创建对象。
回到我们的问题,什么是反射或者说为什么我们要用到反射?
就是当我们在编译期没办法指定生成对象的时候,我们只能运用反射来创建对象。
2.获取Class的几种方式
一共有三种方式,除了上面图中的那种还有下面这两种
//1. 类.class
Class personClazz1 = Person.class;
//2. 对象.getClass()
Person person = new Person();
Class personClazz2 = person.getClass();
这里一个小问题,那么这三种方式生成的personClazz == personClazz1 、personClazz1 == personClazz2的结果是什么?
答案,都是true。因为不管哪种方式获得的personClazz 都只是我们编译出来的class文件的一个实例,所以他们都是相同的。
PS1:通过clazz我们也可以获取字段、方法等。这里不一一介