class="markdown_views prism-atom-one-dark">
Java 基础: 浅谈类型基础 - Class 对象
简介
本文的起因要说到最近在研究 Spring Cloud 的多种服务。由于入门时直接从 Spring Boot 入门,大部分的服务或依赖都已经封装的非常完善,开箱即用,反而对于底层的运行机制不慎了解。作为一个有抱负的程序员(bushi,不能接受这样懵懵懂懂瞎用,所以就打算从应用底层的 Java 反射 机制(Reflect)
从头学习一遍。
本篇将作为学习 Java 反射 的预备知识,在真正进入反射 之前我们先来了解以下什么是 Class 对象
,它在 Java 运行的过程中扮演什么样的角色。
参考
Thinking in Java - 原书第 4 版 深入理解 Java 虚拟机 - 周志明 Java中Class对象详解 https://blog.csdn.net/mcryeasy/article/details/52344729 class ="tags" href="/tags/JAVA.html" title=java>java中类加载时机https://www.cnblogs.com/aspirant/p/9036010.html
正文
浅谈 Class 对象的前生后世
要运行 Java 就得要从 JVM(Java Virtual Machine)谈起。学过一点 Java 的应该都知道,与 C/C++ 直接编译成二进制文件不同,Java 会将源文件编译成 .class
字节码,并在运行时由 JVM 动态加载。
在 Java 的世界中万物皆对象(Object),而在强类型的限制下每个对象势必有自己的类型,Java 编译(compile)
时就会为每个类型(class )生成一个 .class 文件。接下来就轮到运行(runtime)
时的主角 JVM 登场了,JVM 解析 .class 文件的过程可粗略分成三个阶段:
加载(Load):由类加载器(Class Loader)
通过全限定名(包名+类名)
加载代表 .class 文件的二进制流,并由该字节码生成一个 Class 对象
。
链接(Link):验证 .class 文件中的信息有效性和正确性、静态域空间分配和初始化、常量池符号引用。
初始化(initialize):真正开始运行对象内容,静态块初始化(static {}
)、若存在父类则优先初始化父类。
这边我们最关心的是第一个阶段的 Class 对象
,它也是 JVM 运行时最核心的部分,有了 Class 对象才有类型的存在。
备注:有关 JVM 运行机制、.class 文件结构、类加载器(Class Loader)等内容可以参考其他资料,本篇不再细说。
Class 对象的加载时机
Class 对象通常会在第一次使用
时被 JVM 加载,而所谓的"第一次使用"可以是:
创建对象实例(使用 new
关键字) 访问静态域(XXX.field
或是 XXX.func()
) 透过反射 (class ="tags" href="/tags/JAVA.html" title=java>java.lang.reflect
)机制对类方法进行调用时 子类正在被加载 运行时指定的主类(运行主入口 main
所在的类)
也就是说 JVM 并不会一次创建甚至加载好所有类型,而是按需加载(懒加载)
。这部分就使得 JVM 有很大的可伸缩性,我们可以修改类加载的规则,也可以在运行后才动态的输入二进制流来添加新的类型,使得 Java 语言天生能和网络结合在一起,只要存在于更大的网络之中就能够动态接受二进制流以识别新的类型。
初识 Class 对象
说了这么多,我们马上就来看看 Class 对象到底都躲在哪里
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test1class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class -name">Test class="token punctuation">{
class="token keyword">public class="token keyword">static class="token keyword">void class="token function">main class="token punctuation">( Stringclass="token punctuation">[ class="token punctuation">] argsclass="token punctuation">) class="token punctuation">{
Class class="token class -name">c class="token operator">= Testclass="token punctuation">. class="token keyword">class class="token punctuation">;
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"Test.class : " class="token operator">+ cclass="token punctuation">) class="token punctuation">;
Test t1 class="token operator">= class="token keyword">new class="token class -name">Test class="token punctuation">( class="token punctuation">) class="token punctuation">;
Test t2 class="token operator">= class="token keyword">new class="token class -name">Test class="token punctuation">( class="token punctuation">) class="token punctuation">;
Test t3 class="token operator">= class="token keyword">new class="token class -name">Test class="token punctuation">( class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( c class="token operator">== t1class="token punctuation">. class="token function">getClass class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( c class="token operator">== t2class="token punctuation">. class="token function">getClass class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( c class="token operator">== t3class="token punctuation">. class="token function">getClass class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
Test.class : class com.example.class object.test1.Test
true
true
true
最简单的方法我们直接调用 Test.class
就可以拿到该类型的 Class 对象,我们也可以调用对象实例的 getClass()
方法获取 Class 对象。注意!由于 Class 对象是与类型一一对应的,所以不管是直接调用 Test.class
或是 t1.getClass()
,其所指向的 Class 对象都是同一个,如下图所示
Class 类型方法
下面我们简单介绍以下 Class 类型的可用接口(这边仅仅谈论与类型相关的,Field
、Method
相关的留到反射 的篇幅说明)
静态方法
Static Method Description static Class forName(String) 根据传入的全限定名查找 Class 对象(第一次访问会进行类加载)
获取类信息方法
Method Description String getName() 获取类型名称 String getSimpleName() 获取简单名称(省略包名) String getCanonicalName() 获取标准完整名称 Class getSuperclass () 获取父类的 Class 对象 Class[] getInterfaces() 获取实现接口的 Class 对象列表
构造方法 & 类型转换
Method Description Object newInstance() 创建类型实例 T cast(Class<T>) 类型转换
类型检查
Method Description isMemberClass() 检查是否为内部类 isInterface() 检查是否为接口 isEnum() 检查是否为枚举 isAnnotation() 检查是否为注解 isArray() 检查是否为数组 isPrimitive() 检查是否为内置 isAnonymousClass() 检查是否为匿名类 isLocalClass() 检查是否为局部类
下面我们就给出几个 Class 对象方法测试
获取类信息
类型定义
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token comment">/* IA.class ="tags" href="/tags/JAVA.html" title=java>java */
class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test1class="token punctuation">;
class="token keyword">public class="token keyword">interface class="token class -name">IA class="token punctuation">{ class="token punctuation">}
class="token comment">/* IB.class ="tags" href="/tags/JAVA.html" title=java>java */
class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test1class="token punctuation">;
class="token keyword">public class="token keyword">interface class="token class -name">IB class="token punctuation">{ class="token punctuation">}
class="token comment">/* IC.class ="tags" href="/tags/JAVA.html" title=java>java */
class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test1class="token punctuation">;
class="token keyword">public class="token keyword">interface class="token class -name">IC class="token punctuation">{ class="token punctuation">}
class="token comment">/* A.class ="tags" href="/tags/JAVA.html" title=java>java */
class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test1class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class -name">A class="token punctuation">{
class="token function">A class="token punctuation">( class="token punctuation">) class="token punctuation">{ class="token punctuation">}
class="token function">A class="token punctuation">( class="token keyword">int iclass="token punctuation">) class="token punctuation">{ class="token punctuation">}
class="token punctuation">}
class="token comment">/* B.class ="tags" href="/tags/JAVA.html" title=java>java */
class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test1class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class -name">B class="token keyword">extends class="token class -name">A class="token keyword">implements class="token class -name">IA class="token punctuation">, IBclass="token punctuation">, IC class="token punctuation">{
class="token function">B class="token punctuation">( class="token punctuation">) class="token punctuation">{ class="token keyword">super class="token punctuation">( class="token number">1 class="token punctuation">) class="token punctuation">; class="token punctuation">}
class="token punctuation">}
测试类
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test1class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class -name">Main class="token punctuation">{
class="token comment">/**
* 查看 Class 对象信息
* @param c
*/
class="token keyword">private class="token keyword">static class="token keyword">void class="token function">info class="token punctuation">( Class class="token class -name">c class="token punctuation">) class="token punctuation">{
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"----- info -----" class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"Class name: " class="token operator">+ cclass="token punctuation">. class="token function">getName class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">; class="token comment">// 获取类型名称
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"is interface: " class="token operator">+ cclass="token punctuation">. class="token function">isInterface class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">; class="token comment">// 检查是否为接口
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"Simple name: " class="token operator">+ cclass="token punctuation">. class="token function">getSimpleName class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">; class="token comment">// 简单名称
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"Canonical name: " class="token operator">+ cclass="token punctuation">. class="token function">getCanonicalName class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">; class="token comment">// 全限定名
class="token punctuation">}
class="token keyword">public class="token keyword">static class="token keyword">void class="token function">main class="token punctuation">( Stringclass="token punctuation">[ class="token punctuation">] argsclass="token punctuation">) class="token punctuation">{
Class class="token class -name">c class="token operator">= nullclass="token punctuation">;
class="token keyword">try class="token punctuation">{
class="token comment">// 获取 B 类型的 Class 对象
c class="token operator">= Classclass="token punctuation">. class="token function">forName class="token punctuation">( class="token string">"com.example.class object.test1.B" class="token punctuation">) class="token punctuation">;
class="token punctuation">} class="token keyword">catch class="token punctuation">( class="token class -name">ClassNotFoundException eclass="token punctuation">) class="token punctuation">{
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"B not found" class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. class="token function">exit class="token punctuation">( class="token number">1 class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token function">info class="token punctuation">( cclass="token punctuation">) class="token punctuation">; class="token comment">// 展示 B 类型的 Class 对象信息
class="token keyword">for class="token punctuation">( Class class="token class -name">i class="token operator">: cclass="token punctuation">. class="token function">getInterfaces class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">{
class="token function">info class="token punctuation">( iclass="token punctuation">) class="token punctuation">; class="token comment">// 展示 B 类型的所有接口 Class 信息
class="token punctuation">}
Class class="token class -name">pc class="token operator">= cclass="token punctuation">. class="token function">getSuperclass class="token punctuation">( class="token punctuation">) class="token punctuation">; class="token comment">// 获取父类即 A 的 Class 对象
Object p class="token operator">= nullclass="token punctuation">;
class="token keyword">try class="token punctuation">{
p class="token operator">= pcclass="token punctuation">. class="token function">newInstance class="token punctuation">( class="token punctuation">) class="token punctuation">; class="token comment">// 创建父类实例
class="token punctuation">} class="token keyword">catch class="token punctuation">( class="token class -name">InstantiationException eclass="token punctuation">) class="token punctuation">{
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"unable to instantiate" class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. class="token function">exit class="token punctuation">( class="token number">1 class="token punctuation">) class="token punctuation">;
class="token punctuation">} class="token keyword">catch class="token punctuation">( IllegalAccessException eclass="token punctuation">) class="token punctuation">{
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"unable to access" class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. class="token function">exit class="token punctuation">( class="token number">1 class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token function">info class="token punctuation">( pclass="token punctuation">. class="token function">getClass class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">; class="token comment">// 由对象获取 Class 信息(类型为 A)
class="token punctuation">}
class="token punctuation">}
输出
----- info -----
Class name: com.example.class object.test1.B
is interface: false
Simple name: B
Canonical name: com.example.class object.test1.B
----- info -----
Class name: com.example.class object.test1.IA
is interface: true
Simple name: IA
Canonical name: com.example.class object.test1.IA
----- info -----
Class name: com.example.class object.test1.IB
is interface: true
Simple name: IB
Canonical name: com.example.class object.test1.IB
----- info -----
Class name: com.example.class object.test1.IC
is interface: true
Simple name: IC
Canonical name: com.example.class object.test1.IC
----- info -----
Class name: com.example.class object.test1.A
is interface: false
Simple name: A
Canonical name: com.example.class object.test1.A
获取类型继承链
第二个例子我们演示如何获取一个类型的完整继承链
类型定义
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token comment">/* A.class ="tags" href="/tags/JAVA.html" title=java>java */
class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test2class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class -name">A class="token punctuation">{ class="token punctuation">}
class="token comment">/* B.class ="tags" href="/tags/JAVA.html" title=java>java */
class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test2class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class -name">B class="token keyword">extends class="token class -name">A class="token punctuation">{ class="token punctuation">}
class="token comment">/* C.class ="tags" href="/tags/JAVA.html" title=java>java */
class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test2class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class -name">C class="token keyword">extends class="token class -name">B class="token punctuation">{ class="token punctuation">}
测试类
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test2class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class -name">Main class="token punctuation">{
class="token keyword">private class="token keyword">static class="token keyword">void class="token function">printInheritList class="token punctuation">( Class class="token class -name">c class="token punctuation">) class="token punctuation">{
Class class="token class -name">pc class="token punctuation">;
class="token comment">// 递归检索父类,直到 null(Object.class .getSuperclass () 为 null)
class="token keyword">while class="token punctuation">( class="token punctuation">( pc class="token operator">= cclass="token punctuation">. class="token function">getSuperclass class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token operator">!= nullclass="token punctuation">) class="token punctuation">{
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( cclass="token punctuation">. class="token function">getName class="token punctuation">( class="token punctuation">) class="token operator">+ class="token string">" extends " class="token operator">+ pcclass="token punctuation">. class="token function">getName class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">;
c class="token operator">= pcclass="token punctuation">;
class="token punctuation">}
class="token punctuation">}
class="token keyword">public class="token keyword">static class="token keyword">void class="token function">main class="token punctuation">( Stringclass="token punctuation">[ class="token punctuation">] argsclass="token punctuation">) class="token punctuation">{
class="token keyword">try class="token punctuation">{
Class class="token class -name">c class="token operator">= Classclass="token punctuation">. class="token function">forName class="token punctuation">( class="token string">"com.example.class object.test2.C" class="token punctuation">) class="token punctuation">;
class="token function">printInheritList class="token punctuation">( cclass="token punctuation">) class="token punctuation">;
class="token punctuation">} class="token keyword">catch class="token punctuation">( class="token class -name">ClassNotFoundException eclass="token punctuation">) class="token punctuation">{
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"Class C not found" class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. class="token function">exit class="token punctuation">( class="token number">1 class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
class="token punctuation">}
输出
com.example.class object.test2.C extends com.example.class object.test2.B
com.example.class object.test2.B extends com.example.class object.test2.A
com.example.class object.test2.A extends class ="tags" href="/tags/JAVA.html" title=java>java.lang.Object
我们可以看到最简单的类型 A 默认是继承 Object 类型的,也就是所有对象(类型)的祖先类型必定是 Object。
创建对象实例 & 类型转换
第三个例子我们透过 Class 对象来动态创建类型实例,并给出一般类型转换之外的另一种方法。
类型定义
SuperClass.class ="tags" href="/tags/JAVA.html" title=java>java
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test3class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class -name">SuperClass class="token punctuation">{
class="token comment">// 无参数构造函数
class="token keyword">public class="token function">SuperClass class="token punctuation">( class="token punctuation">) class="token punctuation">{
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"SuperClass()" class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token comment">// 带参数构造函数
class="token keyword">public class="token function">SuperClass class="token punctuation">( class="token keyword">int iclass="token punctuation">) class="token punctuation">{
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"SuperClass(int i)" class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
SubClass.class ="tags" href="/tags/JAVA.html" title=java>java
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test3class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class -name">SubClass class="token keyword">extends class="token class -name">SuperClass class="token punctuation">{
class="token comment">// 无参数构造函数
class="token keyword">public class="token function">SubClass class="token punctuation">( class="token punctuation">) class="token punctuation">{
class="token keyword">super class="token punctuation">( class="token number">1 class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"SubClass()" class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
测试类
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test3class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class -name">Main class="token punctuation">{
class="token keyword">public class="token keyword">static class="token keyword">void class="token function">main class="token punctuation">( Stringclass="token punctuation">[ class="token punctuation">] argsclass="token punctuation">) class="token punctuation">{
class="token function">testSuperClassInstance class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token function">testTypeCasting class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token keyword">private class="token keyword">static class="token keyword">void class="token function">testSuperClassInstance class="token punctuation">( class="token punctuation">) class="token punctuation">{
class="token keyword">try class="token punctuation">{
Classclass="token generics function">class="token punctuation">< SubClassclass="token punctuation">> c class="token operator">= SubClassclass="token punctuation">. class="token keyword">class class="token punctuation">; class="token comment">// 子类 Class 对象
SubClass subClass class="token operator">= cclass="token punctuation">. class="token function">newInstance class="token punctuation">( class="token punctuation">) class="token punctuation">; class="token comment">// 创建子类实例
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"after create subClass" class="token punctuation">) class="token punctuation">;
class="token comment">// pc.newInstance return type "capture of ? super SubClass"
Classclass="token operator">< class="token operator">? class="token keyword">super SubClassclass="token operator">> pc class="token operator">= cclass="token punctuation">. class="token function">getSuperclass class="token punctuation">( class="token punctuation">) class="token punctuation">; class="token comment">// 父类 Class对象
Object superClass class="token operator">= pcclass="token punctuation">. class="token function">newInstance class="token punctuation">( class="token punctuation">) class="token punctuation">; class="token comment">// 创建父类实例
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"after create superClass" class="token punctuation">) class="token punctuation">;
class="token punctuation">} class="token keyword">catch class="token punctuation">( class="token class -name">IllegalAccessException eclass="token punctuation">) class="token punctuation">{
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"Illegal access" class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. class="token function">exit class="token punctuation">( class="token number">1 class="token punctuation">) class="token punctuation">;
class="token punctuation">} class="token keyword">catch class="token punctuation">( class="token class -name">InstantiationException eclass="token punctuation">) class="token punctuation">{
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"Instantiation error" class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. class="token function">exit class="token punctuation">( class="token number">1 class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
class="token keyword">private class="token keyword">static class="token keyword">void class="token function">testTypeCasting class="token punctuation">( class="token punctuation">) class="token punctuation">{
SuperClass sup class="token operator">= class="token keyword">new class="token class -name">SubClass class="token punctuation">( class="token punctuation">) class="token punctuation">;
Classclass="token generics function">class="token punctuation">< SubClassclass="token punctuation">> subType class="token operator">= SubClassclass="token punctuation">. class="token keyword">class class="token punctuation">;
class="token comment">// 另一种类型转换 cast()
class="token comment">// SubClass.class .cast(obj) 与 (SubClass) obj 等价
SubClass sub class="token operator">= subTypeclass="token punctuation">. class="token function">cast class="token punctuation">( supclass="token punctuation">) class="token punctuation">; class="token comment">// equals: sub = (SubClass) sup;
class="token punctuation">}
class="token punctuation">}
输出
SuperClass(int i)
SubClass()
after create subClass
SuperClass()
after create superClass
SuperClass(int i)
SubClass()
我们可以看到,当我们使用 newInstance()
方法只能调用默认构造函数,待到反射 的时候我们再来看看要如何调用带参数构造函数(良好的代码风格可以使用设计模式
中的工厂方法来取代重载构造函数)。
类型检查
最后一个例子是检测 Class 对象的类型。在 Java 中一个 class 可能有各种形态:一般类型、内部类型、枚举类型、注解类型、数组类型、内置类型、匿名类型、局部类型,这些信息 Class 对象也能识别!马上来看看
类型定义
A.class ="tags" href="/tags/JAVA.html" title=java>java
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test4class="token punctuation">;
class="token comment">// 一般类型
class="token keyword">public class="token keyword">class class="token class -name">A class="token punctuation">{
class="token comment">// 内部类型
class="token keyword">public class="token keyword">class class="token class -name">B class="token punctuation">{
class="token punctuation">}
class="token punctuation">}
C.class ="tags" href="/tags/JAVA.html" title=java>java
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test4class="token punctuation">;
class="token comment">// 接口类型
class="token keyword">public class="token keyword">interface class="token class -name">C class="token punctuation">{ class="token punctuation">}
D.class ="tags" href="/tags/JAVA.html" title=java>java
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test4class="token punctuation">;
class="token comment">// 枚举类型
class="token keyword">public class="token keyword">enum D class="token punctuation">{ class="token punctuation">}
E.class ="tags" href="/tags/JAVA.html" title=java>java
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test4class="token punctuation">;
class="token comment">// 注解类型
class="token keyword">public @class="token keyword">interface class="token class -name">E class="token punctuation">{ class="token punctuation">}
F.class ="tags" href="/tags/JAVA.html" title=java>java
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test4class="token punctuation">;
class="token keyword">public class="token keyword">abstract class="token keyword">class class="token class -name">F class="token punctuation">{
class="token keyword">public class="token keyword">static F class="token function">createAnonymous class="token punctuation">( class="token punctuation">) class="token punctuation">{
class="token comment">// 匿名类型
class="token keyword">return class="token keyword">new class="token class -name">F class="token punctuation">( class="token punctuation">) class="token punctuation">{
class="token punctuation">} class="token punctuation">;
class="token punctuation">}
class="token keyword">public class="token keyword">static F class="token function">createLocal class="token punctuation">( class="token punctuation">) class="token punctuation">{
class="token comment">// 局部类型
class="token keyword">class class="token class -name">G class="token keyword">extends class="token class -name">F class="token punctuation">{ class="token punctuation">}
class="token keyword">return class="token keyword">new class="token class -name">G class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
测试类
class="prism language-class ="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package comclass="token punctuation">. exampleclass="token punctuation">. class objectclass="token punctuation">. test4class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class -name">Test class="token punctuation">{
class="token keyword">public class="token keyword">static class="token keyword">void class="token function">main class="token punctuation">( Stringclass="token punctuation">[ class="token punctuation">] argsclass="token punctuation">) class="token punctuation">{
class="token function">check class="token punctuation">( Aclass="token punctuation">. class="token keyword">class class="token punctuation">) class="token punctuation">; class="token comment">// 一般类
class="token function">check class="token punctuation">( Aclass="token punctuation">. Bclass="token punctuation">. class="token keyword">class class="token punctuation">) class="token punctuation">; class="token comment">// 内部类
class="token function">check class="token punctuation">( Cclass="token punctuation">. class="token keyword">class class="token punctuation">) class="token punctuation">; class="token comment">// 接口类
class="token function">check class="token punctuation">( Dclass="token punctuation">. class="token keyword">class class="token punctuation">) class="token punctuation">; class="token comment">// 枚举类
class="token function">check class="token punctuation">( Eclass="token punctuation">. class="token keyword">class class="token punctuation">) class="token punctuation">; class="token comment">// 注解类
class="token function">check class="token punctuation">( class="token keyword">int class="token punctuation">. class="token keyword">class class="token punctuation">) class="token punctuation">; class="token comment">// 内置类
class="token function">check class="token punctuation">( class="token keyword">new class="token class -name">int class="token punctuation">[ class="token number">0 class="token punctuation">] class="token punctuation">. class="token function">getClass class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">; class="token comment">// 数组类
class="token function">check class="token punctuation">( Fclass="token punctuation">. class="token function">createAnonymous class="token punctuation">( class="token punctuation">) class="token punctuation">. class="token function">getClass class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">; class="token comment">// 匿名类
class="token function">check class="token punctuation">( Fclass="token punctuation">. class="token function">createLocal class="token punctuation">( class="token punctuation">) class="token punctuation">. class="token function">getClass class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">; class="token comment">// 局部类
class="token punctuation">}
class="token keyword">private class="token keyword">static class="token keyword">void class="token function">check class="token punctuation">( Class class="token class -name">c class="token punctuation">) class="token punctuation">{
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"----- check " class="token operator">+ cclass="token punctuation">. class="token function">getSimpleName class="token punctuation">( class="token punctuation">) class="token operator">+ class="token string">" -----" class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"isMemberClass: " class="token operator">+ cclass="token punctuation">. class="token function">isMemberClass class="token punctuation">( class="token punctuation">) class="token operator">+ class="token string">", isInterface: " class="token operator">+ cclass="token punctuation">. class="token function">isInterface class="token punctuation">( class="token punctuation">) class="token operator">+ class="token string">", isEnum: " class="token operator">+ cclass="token punctuation">. class="token function">isEnum class="token punctuation">( class="token punctuation">) class="token operator">+ class="token string">", isAnnotation: " class="token operator">+ cclass="token punctuation">. class="token function">isAnnotation class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">;
Systemclass="token punctuation">. outclass="token punctuation">. class="token function">println class="token punctuation">( class="token string">"isArray: " class="token operator">+ cclass="token punctuation">. class="token function">isArray class="token punctuation">( class="token punctuation">) class="token operator">+ class="token string">", isPrimitive: " class="token operator">+ cclass="token punctuation">. class="token function">isPrimitive class="token punctuation">( class="token punctuation">) class="token operator">+ class="token string">", isAnonymousClass: " class="token operator">+ cclass="token punctuation">. class="token function">isAnonymousClass class="token punctuation">( class="token punctuation">) class="token operator">+ class="token string">", isLocalClass: " class="token operator">+ cclass="token punctuation">. class="token function">isLocalClass class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
输出
----- check A -----
isMemberClass: false, isInterface: false, isEnum: false, isAnnotation: false
isArray: false, isPrimitive: false, isAnonymousClass: false, isLocalClass: false
----- check B -----
isMemberClass: true, isInterface: false, isEnum: false, isAnnotation: false
isArray: false, isPrimitive: false, isAnonymousClass: false, isLocalClass: false
----- check C -----
isMemberClass: false, isInterface: true, isEnum: false, isAnnotation: false
isArray: false, isPrimitive: false, isAnonymousClass: false, isLocalClass: false
----- check D -----
isMemberClass: false, isInterface: false, isEnum: true, isAnnotation: false
isArray: false, isPrimitive: false, isAnonymousClass: false, isLocalClass: false
----- check E -----
isMemberClass: false, isInterface: true, isEnum: false, isAnnotation: true
isArray: false, isPrimitive: false, isAnonymousClass: false, isLocalClass: false
----- check int -----
isMemberClass: false, isInterface: false, isEnum: false, isAnnotation: false
isArray: false, isPrimitive: true, isAnonymousClass: false, isLocalClass: false
----- check int[] -----
isMemberClass: false, isInterface: false, isEnum: false, isAnnotation: false
isArray: true, isPrimitive: false, isAnonymousClass: false, isLocalClass: false
----- check -----
isMemberClass: false, isInterface: false, isEnum: false, isAnnotation: false
isArray: false, isPrimitive: false, isAnonymousClass: true, isLocalClass: false
----- check G -----
isMemberClass: false, isInterface: false, isEnum: false, isAnnotation: false
isArray: false, isPrimitive: false, isAnonymousClass: false, isLocalClass: true
输出看起来有些吓人,不过就是一些类型信息
完整代码仓库
https://github.com/superfreeeee/Blog-code/tree/main/back_end/class ="tags" href="/tags/JAVA.html" title=java>java/class ="tags" href="/tags/JAVA.html" title=java>java_class _object
结语
本篇稍微介绍了 Class 对象的来由还有一些基本类型相关的方法,下一期将开始正式进入 Java 反射
的环节。