• 让天下没有难学的技术
    多数学员都来自推荐,这就是口碑的力量

Java开发基础之反射

开始想要做数据的念头比较晚,而大多数的大数据都是 Java 开发的,学习 Java 也逐渐排上日程,这一系列的相关主题是随着学习大数据相关技术的过程中对于一些疑问和技术点,逐渐完善补充的。希望这趟旅程可以收获和分享知识。

本文从问题的角度,了解反射,会从以下几个角度进行解析:

  1. 什么是反射,反射的概念以及可以获取到的信息

  2. 如何使用反射

  3. 如何利用反射并结合 Flink 中类型定义的角度解析反射的应用

什么是反射

反射就是 Reflection,Java 中超类是Object类,即所有的 Java 类都是Object类。Java 的反射解决的是程序在运行期可以拿到Class对象的所有信息。对于 Java 小白这里涉及两个问题:

什么是Class对象?

Class对象包含哪些信息?

下面就从这两个角度进行更深入的了解。

Class 对象

Class 对象在编译阶段编译器在.class文件中生成Class对象,在加载阶段,通过 JVM 加载机制将其加载到内存中。反射是在运行阶段获取 Class 对象的信息。

在 Java 中有两种对象:

Class 对象:Class 对象是 JVM 生成用来保存对象的类的信息的。

实例对象:实例对象是类的实例,通常是通过new关键字构建的。

Java 程序执行之前需要经过编译、加载、链接和初始化几个阶段,编译阶段会将源码文件编译为.class字节码文件,编译器同时会在.class文件中生成 Class 对象,加载阶段通过 JVM 内部的类加载机制,将 Class 对象加载到内存中。在创建对象实例之前,JVM 会先检查 Class 对象是否在内存中存在,如果不存在,则加载 Class 对象,然后再创建对象实例,如果存在,则直接根据 Class 对象创建对象实例。JVM 中只有一个 Class 对象,但可以根据 Class 对象生成多个对象实例[1]。

那么,Class对象包含哪些信息?

类属性信息,即 Field

类的构造方法的信息

类方法

正在运行的 Java 应用程序中的类的实例

反射的使用

关于反射的使用,网上有很多资料,我主要从获取 Class 对象方式以及通过获取到的Class对象创建对象实例两个角度进行介绍。

获取 Class 对象的方式

方式一:通过Class.forName静态方法,输入类的全路径来获取 Class 对象

Class cls1 = Class.forName(“base.basic.Person”);

复制代码

方式二:通过.class方法,该方法仅限于编译前已知类名

Class cls2 = Person.class;

复制代码

方式三:通过类实例的getClass

Person person = new Person(“Lily”, 18);Class cls3 = person.getClass();

复制代码

通过 Class 对象创建对象实例的方式

方式一: 通过Class对象的newInstance()方法, 只支持无参构造

Person person1 = (Person)cls1.newInstance();

复制代码

方式二: 通过Constructor对象的newInstance()方法,该方式支持有参构造

Constructor constructor = cls1.getConstructor(String.class, Integer.class);Person person2 = (Person)constructor.newInstance(“Lucy”, 30);

复制代码

相关的实现我存放在我的GitHub上了,另外实现了简单的

获取Class对象的属性信息

获取Class对象的方法的

实例,主要是基于了解该方法的使用,有兴趣的可以看一下。

开源应用

我是在学习 Flink 支持的数据类型时,了解到 Flink 数据类型的描述信息都是TypeInformation,在查看相关代码实现的过程中看到反射,借此机会将相关的信息也在此进行一个记录。

Flink 中关于类型相关的实现位于

flink\flink-core\src\main\java\org\apache\flink\api\common\typeinfo\目录下,以ValueTypeInfo为例来,相关的类图如下:

其中,ValueTypeInfo中构造函数的入参便是通过反射机制中的Class对象。

public ValueTypeInfo(Class<T> type) { this.type = checkNotNull(type);
checkArgument( Value.class.isAssignableFrom(type) || type.equals(Value.class), “ValueTypeInfo can only be used for subclasses of %s”, Value.class.getName()); }

复制代码

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注