博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
类字面常量
阅读量:6723 次
发布时间:2019-06-25

本文共 2474 字,大约阅读时间需要 8 分钟。

系列文描述:

  该文章是日常笔记系列的第二篇第三节,记录了类字面常量的特殊性,相信看完肯定有所收获。

关于类字面常量
描述:

最近接触了比较多的反射,了解到类字面常量特殊的地方,故做笔录,同时也和大家分享下类字面常量特殊在哪里。所谓的类字面常量指的是A.class,这是java提供的生成对Class对象的引用。关于类的概念我们都很熟悉,关于类的使用JDK大致为我们做了三步操作,分别是

  • 加载,这是由类加载器执行的,用白话来描述就是查找这个类的字节码,然后构建一个Class对象。
  • 链接,在这个阶段会先校验类的字节码,并且为类对象的静态域分配好内存空间。
  • 初始化,首先会先初始化类的超类(前提是有超类),以及执行静态初始化器和静态初始化块。

了解了三步还不够,我们还要知道jdk其实超级无敌懒的,对类的初始化这一步会延迟到对静态方法或者“非”常静态域进行首次引用时才执行。这里的常静态域指的是被static final修饰的常量,该常量不需要对应类初始化就可以被读取。为了更加清晰的了解到这个过程,可以看以下demo。

代码演示:
package classLoader;import java.util.Random;class Initable1 {    static final int staticFinal = 47;    static final int staticFinal2 = (int) (Math.random() * 1000);    static {        System.out.println("Initializing Initable1");    }}class Initable2 {    static int staticNonFinal = 147;    static {        System.out.println("Initializing Initable2");    }}class Initable3 {    static int staticNonFinal = 74;    static {        System.out.println("Initializing Initable3");    }}public class ClassInitialization {    public static Random random = new Random(47);    public static void main(String[] args) throws ClassNotFoundException {        Class initable1 = Initable1.class;        System.out.println("After creating Initable1 ref");        System.out.println(Initable1.staticFinal);        System.out.println(Initable1.staticFinal2);        System.out.println(Initable2.staticNonFinal);        Class initable3 = Class.forName("classLoader.Initable3");        System.out.println("After creating Initable3 ref");        System.out.println(Initable3.staticNonFinal);    }}复制代码

看具体运行结果前,看官先自己用草稿写下输出答案哈,这样比较有效果。 运行结果如下:

After creating INitable ref47Initializing Initable1604Initializing Initable2147Initializing Initable3After creating Initable3 ref74复制代码

如果答案一样,那么可以直接忽略掉我接下来的解析了哈,因为分析很绕,主要是验证上面的理论!

正如答案中看到的那样,47 在 After creating INitable ref 后才输出,证明了 Class initable1 = Initable1.class 这一行代码运行的时候并没有立即初始化类,而 Initializing Initable1 在47后才输出也验证了另一个观点(47对应的Field staticFinal是被static final 修饰的常静态域),那就是常静态域不需要在类Initable1进行初始化就可以被读取。而在打印结果Initable1.staticFinal2(随机数)之前先打印出了Initable1静态代码块中的输出,意味着直到这一步才真正初始化了类Initable1,于是先执行了静态代码块再输出了Initable1.staticFinal2,同样,对Initable2.staticNonFinal的输出先打印了Initable2静态代码块中的Initializing Initable2也是同样的原因。而在最后使用Class.forName("classLoader.Initable3")取得Initable3类的引用的时候直接打印了代码块中的字符串可以看出,使用Class.forName取得类的引用的时候是立即初始化类的。

结尾说点什么

说好的一周一篇,上个周末沉迷docker的使用导致废了,然后最近又是每天都是差不多十二点下班,所以只能下班后花时间写总结最近的笔记了(  ̄▽ ̄)((≧︶≦)


系列博客可以关注公众号:

个人网站:

转载于:https://juejin.im/post/5c9b9ed3e51d451efb187302

你可能感兴趣的文章
C++嵌套类的学习
查看>>
PPAS可以安装分区表
查看>>
简单选择排序
查看>>
LintCode-最大子数组差
查看>>
GDB十分钟教程
查看>>
SQL中 decode()函数简介 - FreeSpider - 博客园
查看>>
Java开发人员常用的服务配置(Nginx、Tomcat、JVM、Mysql、Redis)
查看>>
[剑指offer] 从尾到头打印链表
查看>>
最新Android Glide4.0加载Gif图片到ImageView
查看>>
Spring Security实现RBAC权限管理
查看>>
可以用TFTP,或者FTP直接下载。 你也可以用软件CRT中执行show start-config
查看>>
[数据结构]双机调度问题
查看>>
完成端口与高性能服务器程序开发(转)
查看>>
前端开发学习笔记一
查看>>
linux iscsi initiator 安装配置
查看>>
oracle中exp/imp详解
查看>>
下载器-http 进度条 文件读写
查看>>
[20160919]Result cache问题.txt
查看>>
Linux系统硬盘读写测试
查看>>
移动端点击300ms延迟
查看>>