Java 基础: 浅谈类型基础 - Class 对象

news/2024/5/19 5:44:15 标签: java, jvm, class, 反射
class="baidu_pl">
class="article_content clearfix">
class="markdown_views prism-atom-one-dark">

Java 基础: 浅谈类型基础 - Class 对象

class="toc">

文章目录

  • Java 基础: 浅谈类型基础 - Class 对象
    • 简介
    • 参考
  • 正文
    • 浅谈 Class 对象的前生后世
      • Class 对象的加载时机
    • 初识 Class 对象
    • 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">.classobjectclass="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">mainclass="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">classclass="token punctuation">;
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="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">Testclass="token punctuation">(class="token punctuation">)class="token punctuation">;
        Test t2 class="token operator">= class="token keyword">new class="token class-name">Testclass="token punctuation">(class="token punctuation">)class="token punctuation">;
        Test t3 class="token operator">= class="token keyword">new class="token class-name">Testclass="token punctuation">(class="token punctuation">)class="token punctuation">;
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(c class="token operator">== t1class="token punctuation">.class="token function">getClassclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(c class="token operator">== t2class="token punctuation">.class="token function">getClassclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(c class="token operator">== t3class="token punctuation">.class="token function">getClassclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;
    class="token punctuation">}
class="token punctuation">}
Test.class: class com.example.classobject.test1.Test
true
true
true

最简单的方法我们直接调用 Test.class 就可以拿到该类型的 Class 对象,我们也可以调用对象实例的 getClass() 方法获取 Class 对象。注意!由于 Class 对象是与类型一一对应的,所以不管是直接调用 Test.class 或是 t1.getClass(),其所指向的 Class 对象都是同一个,如下图所示

Class 类型方法

下面我们简单介绍以下 Class 类型的可用接口(这边仅仅谈论与类型相关的,FieldMethod 相关的留到反射的篇幅说明)

静态方法

Static MethodDescription
static Class forName(String)根据传入的全限定名查找 Class 对象(第一次访问会进行类加载)

获取类信息方法

MethodDescription
String getName()获取类型名称
String getSimpleName()获取简单名称(省略包名)
String getCanonicalName()获取标准完整名称
Class getSuperclass()获取父类的 Class 对象
Class[] getInterfaces()获取实现接口的 Class 对象列表

构造方法 & 类型转换

MethodDescription
Object newInstance()创建类型实例
T cast(Class<T>)类型转换

类型检查

MethodDescription
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">.classobjectclass="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">.classobjectclass="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">.classobjectclass="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">.classobjectclass="token punctuation">.test1class="token punctuation">;
class="token keyword">public class="token keyword">class class="token class-name">A class="token punctuation">{
    class="token function">Aclass="token punctuation">(class="token punctuation">) class="token punctuation">{class="token punctuation">}
    class="token function">Aclass="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">.classobjectclass="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">IAclass="token punctuation">, IBclass="token punctuation">, IC class="token punctuation">{
    class="token function">Bclass="token punctuation">(class="token punctuation">) class="token punctuation">{ class="token keyword">superclass="token punctuation">(class="token number">1class="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">.classobjectclass="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">infoclass="token punctuation">(Class class="token class-name">cclass="token punctuation">) class="token punctuation">{
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"----- info -----"class="token punctuation">)class="token punctuation">;
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"Class name: " class="token operator">+ cclass="token punctuation">.class="token function">getNameclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">; class="token comment">// 获取类型名称
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"is interface: " class="token operator">+ cclass="token punctuation">.class="token function">isInterfaceclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">; class="token comment">// 检查是否为接口
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"Simple name: " class="token operator">+ cclass="token punctuation">.class="token function">getSimpleNameclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">; class="token comment">// 简单名称
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"Canonical name: " class="token operator">+ cclass="token punctuation">.class="token function">getCanonicalNameclass="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">mainclass="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">forNameclass="token punctuation">(class="token string">"com.example.classobject.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">printlnclass="token punctuation">(class="token string">"B not found"class="token punctuation">)class="token punctuation">;
            Systemclass="token punctuation">.class="token function">exitclass="token punctuation">(class="token number">1class="token punctuation">)class="token punctuation">;
        class="token punctuation">}

        class="token function">infoclass="token punctuation">(cclass="token punctuation">)class="token punctuation">; class="token comment">// 展示 B 类型的 Class 对象信息
        class="token keyword">forclass="token punctuation">(Class class="token class-name">i class="token operator">: cclass="token punctuation">.class="token function">getInterfacesclass="token punctuation">(class="token punctuation">)class="token punctuation">) class="token punctuation">{
            class="token function">infoclass="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">getSuperclassclass="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">newInstanceclass="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">printlnclass="token punctuation">(class="token string">"unable to instantiate"class="token punctuation">)class="token punctuation">;
            Systemclass="token punctuation">.class="token function">exitclass="token punctuation">(class="token number">1class="token punctuation">)class="token punctuation">;
        class="token punctuation">} class="token keyword">catchclass="token punctuation">(IllegalAccessException eclass="token punctuation">) class="token punctuation">{
            Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"unable to access"class="token punctuation">)class="token punctuation">;
            Systemclass="token punctuation">.class="token function">exitclass="token punctuation">(class="token number">1class="token punctuation">)class="token punctuation">;
        class="token punctuation">}
        class="token function">infoclass="token punctuation">(pclass="token punctuation">.class="token function">getClassclass="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.classobject.test1.B
is interface: false
Simple name: B
Canonical name: com.example.classobject.test1.B
----- info -----
Class name: com.example.classobject.test1.IA
is interface: true
Simple name: IA
Canonical name: com.example.classobject.test1.IA
----- info -----
Class name: com.example.classobject.test1.IB
is interface: true
Simple name: IB
Canonical name: com.example.classobject.test1.IB
----- info -----
Class name: com.example.classobject.test1.IC
is interface: true
Simple name: IC
Canonical name: com.example.classobject.test1.IC
----- info -----
Class name: com.example.classobject.test1.A
is interface: false
Simple name: A
Canonical name: com.example.classobject.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">.classobjectclass="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">.classobjectclass="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">.classobjectclass="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">.classobjectclass="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">printInheritListclass="token punctuation">(Class class="token class-name">cclass="token punctuation">) class="token punctuation">{
        Class class="token class-name">pcclass="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">getSuperclassclass="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">printlnclass="token punctuation">(cclass="token punctuation">.class="token function">getNameclass="token punctuation">(class="token punctuation">) class="token operator">+ class="token string">" extends " class="token operator">+ pcclass="token punctuation">.class="token function">getNameclass="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">mainclass="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">forNameclass="token punctuation">(class="token string">"com.example.classobject.test2.C"class="token punctuation">)class="token punctuation">;
            class="token function">printInheritListclass="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">printlnclass="token punctuation">(class="token string">"Class C not found"class="token punctuation">)class="token punctuation">;
            Systemclass="token punctuation">.class="token function">exitclass="token punctuation">(class="token number">1class="token punctuation">)class="token punctuation">;
        class="token punctuation">}
    class="token punctuation">}
class="token punctuation">}

输出

com.example.classobject.test2.C extends com.example.classobject.test2.B
com.example.classobject.test2.B extends com.example.classobject.test2.A
com.example.classobject.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">.classobjectclass="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">SuperClassclass="token punctuation">(class="token punctuation">) class="token punctuation">{
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="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">SuperClassclass="token punctuation">(class="token keyword">int iclass="token punctuation">) class="token punctuation">{
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="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">.classobjectclass="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">SubClassclass="token punctuation">(class="token punctuation">) class="token punctuation">{
        class="token keyword">superclass="token punctuation">(class="token number">1class="token punctuation">)class="token punctuation">;
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="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">.classobjectclass="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">mainclass="token punctuation">(Stringclass="token punctuation">[class="token punctuation">] argsclass="token punctuation">) class="token punctuation">{
        class="token function">testSuperClassInstanceclass="token punctuation">(class="token punctuation">)class="token punctuation">;
        class="token function">testTypeCastingclass="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">testSuperClassInstanceclass="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">classclass="token punctuation">; class="token comment">// 子类 Class 对象
            SubClass subClass class="token operator">= cclass="token punctuation">.class="token function">newInstanceclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 创建子类实例
            Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="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">getSuperclassclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 父类 Class对象
            Object superClass class="token operator">= pcclass="token punctuation">.class="token function">newInstanceclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 创建父类实例
            Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="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">printlnclass="token punctuation">(class="token string">"Illegal access"class="token punctuation">)class="token punctuation">;
            Systemclass="token punctuation">.class="token function">exitclass="token punctuation">(class="token number">1class="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">printlnclass="token punctuation">(class="token string">"Instantiation error"class="token punctuation">)class="token punctuation">;
            Systemclass="token punctuation">.class="token function">exitclass="token punctuation">(class="token number">1class="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">testTypeCastingclass="token punctuation">(class="token punctuation">) class="token punctuation">{
        SuperClass sup class="token operator">= class="token keyword">new class="token class-name">SubClassclass="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">classclass="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">castclass="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">.classobjectclass="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">.classobjectclass="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">.classobjectclass="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">.classobjectclass="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">.classobjectclass="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">createAnonymousclass="token punctuation">(class="token punctuation">) class="token punctuation">{
        class="token comment">// 匿名类型
        class="token keyword">return class="token keyword">new class="token class-name">Fclass="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">createLocalclass="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">Gclass="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">.classobjectclass="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">mainclass="token punctuation">(Stringclass="token punctuation">[class="token punctuation">] argsclass="token punctuation">) class="token punctuation">{
        class="token function">checkclass="token punctuation">(Aclass="token punctuation">.class="token keyword">classclass="token punctuation">)class="token punctuation">; class="token comment">// 一般类
        class="token function">checkclass="token punctuation">(Aclass="token punctuation">.Bclass="token punctuation">.class="token keyword">classclass="token punctuation">)class="token punctuation">; class="token comment">// 内部类
        class="token function">checkclass="token punctuation">(Cclass="token punctuation">.class="token keyword">classclass="token punctuation">)class="token punctuation">; class="token comment">// 接口类
        class="token function">checkclass="token punctuation">(Dclass="token punctuation">.class="token keyword">classclass="token punctuation">)class="token punctuation">; class="token comment">// 枚举类
        class="token function">checkclass="token punctuation">(Eclass="token punctuation">.class="token keyword">classclass="token punctuation">)class="token punctuation">; class="token comment">// 注解类
        class="token function">checkclass="token punctuation">(class="token keyword">intclass="token punctuation">.class="token keyword">classclass="token punctuation">)class="token punctuation">; class="token comment">// 内置类
        class="token function">checkclass="token punctuation">(class="token keyword">new class="token class-name">intclass="token punctuation">[class="token number">0class="token punctuation">]class="token punctuation">.class="token function">getClassclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">; class="token comment">// 数组类
        class="token function">checkclass="token punctuation">(Fclass="token punctuation">.class="token function">createAnonymousclass="token punctuation">(class="token punctuation">)class="token punctuation">.class="token function">getClassclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">; class="token comment">// 匿名类
        class="token function">checkclass="token punctuation">(Fclass="token punctuation">.class="token function">createLocalclass="token punctuation">(class="token punctuation">)class="token punctuation">.class="token function">getClassclass="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">checkclass="token punctuation">(Class class="token class-name">cclass="token punctuation">) class="token punctuation">{
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"----- check " class="token operator">+ cclass="token punctuation">.class="token function">getSimpleNameclass="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">printlnclass="token punctuation">(class="token string">"isMemberClass: " class="token operator">+ cclass="token punctuation">.class="token function">isMemberClassclass="token punctuation">(class="token punctuation">) class="token operator">+ class="token string">", isInterface: " class="token operator">+ cclass="token punctuation">.class="token function">isInterfaceclass="token punctuation">(class="token punctuation">) class="token operator">+ class="token string">", isEnum: " class="token operator">+ cclass="token punctuation">.class="token function">isEnumclass="token punctuation">(class="token punctuation">) class="token operator">+ class="token string">", isAnnotation: " class="token operator">+ cclass="token punctuation">.class="token function">isAnnotationclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;
        Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"isArray: " class="token operator">+ cclass="token punctuation">.class="token function">isArrayclass="token punctuation">(class="token punctuation">) class="token operator">+ class="token string">", isPrimitive: " class="token operator">+ cclass="token punctuation">.class="token function">isPrimitiveclass="token punctuation">(class="token punctuation">) class="token operator">+ class="token string">", isAnonymousClass: " class="token operator">+ cclass="token punctuation">.class="token function">isAnonymousClassclass="token punctuation">(class="token punctuation">) class="token operator">+ class="token string">", isLocalClass: " class="token operator">+ cclass="token punctuation">.class="token function">isLocalClassclass="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 反射的环节。


http://www.niftyadmin.cn/n/735413.html

相关文章

Java 进阶: Reflect 反射机制(动态获取类内部结构和对象内容、调用方法)

Java 进阶: Reflect 反射机制&#xff08;动态获取类内部结构和对象内容、调用方法&#xff09; 文章目录Java 进阶: Reflect 反射机制&#xff08;动态获取类内部结构和对象内容、调用方法&#xff09;简介参考完整测试代码地址正文获取类定义结构可获取内部信息总览成员变量 …

Ubuntu 20.04桌面文件夹图标消失及文件系统无法打开

前言 之前遇到过服务器上桌面图标突然消失的情况【在更换系统语言之后&#xff0c;桌面出现过一次这种情况&#xff0c;经过重启之后就恢复了】 再后来又莫名其妙出现了这么个问题&#xff0c;最开始搜索的解决方案是 让你打开任务管理器 gnome-system-monitor 找到 nautilu…

关于相机位姿的可视化

Matlab Camera Calibrator 如果使用Matlab的工具箱&#xff0c;有一个集成的可视化工具可以直接使用。 ---- video Python-OpenCV Camera Calibration and 3D Reconstruction Camera calibration With OpenCV C OpenCV Viz模块  这个模块目前只有C版本有 OpenCV 可视化&…

Java 基础: Annotation 注解说明(Spring 建设基础)

Java 基础: Annotation 注解说明(Spring 建设基础) 文章目录Java 基础: Annotation 注解说明(Spring 建设基础)简介参考完整示例代码正文注解的作用注解类型结构Annotation 注解类型RetentionPolicy 生命周期ElementType 可作用类型内置注解内置注解总览DocumentedRetentionTar…

Mvvm 前端数据流框架精讲

原文链接, 如果感兴趣可以加QQ群: 157937068, 一起交流。 本次分享是带大家了解什么是 mvvm&#xff0c;mvvm 的原理&#xff0c;以及近几年产生了哪些演变。 同时借 mvvm 这个话题拓展到对各类前端数据流方案的思考&#xff0c;形成对前端数据流整体认知&#xff0c;帮助大家在…

Ubuntu 20.04 本地Git仓库和Github突然连接不上

问题描述 问题出现在&#xff0c;我想要创建一个新的仓库并关联到Github时&#xff0c;出现了以下报错… 我一开始以为是公钥出了什么问题&#xff0c;就去重置了一下Github上的公钥… 但并没有用… 解决方案 参考链接&#xff1a;git添加公钥后报错sign_and_send_pubkey: s…

Java 应用: Reflect 封装,一次实现使用字符串查找字段、调用方法、打破 private 限制

Java 应用: Reflect 封装&#xff0c;一次实现使用字符串查找字段、调用方法、打破 private 限制 文章目录Java 应用: Reflect 封装&#xff0c;一次实现使用字符串查找字段、调用方法、打破 private 限制简介参考完整示例代码正文实现目标&#xff1a;ReflectUtils 工具类具体…

最大连续子数组的和

题目要求 给定n个整数&#xff08;可能为负数&#xff09;组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]a[i1]…a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0&#xff0c;依此定义&#xff0c;所求的最优值为&#xff1a; Max{0,a[i]a[i1]…a[j]},1<i<…