JVM系列之类的初始化

作者: 简楼 | 来源:发表于2021-03-31 22:03 被阅读0次

类的初始化

前言

类孕育了新的生命周期,那么接下来就是让他健康的茁壮成长,对否?

案例1

public class Client {
    // 静态变量前面
    private static Client client = new Client();

    public static int a;
    public static int b = 0;

    private Client() {
        a++;
        b++;
    }

    public static Client getInstance() {
        return client;
    }

    public static void main(String[] args) {
        Client instance = Client.getInstance();
        System.out.println("a= " + Client.a);
        System.out.println("b= " + Client.b);
    }
}

输出值:

a= 1
b= 0

案例2

public class Client {

    public static int a;
    public static int b = 0;
    // 静态变量后面
    private static Client client = new Client();

    private Client() {
        a++;
        b++;
    }

    public static Client getInstance() {
        return client;
    }

    public static void main(String[] args) {
        Client instance = Client.getInstance();
        System.out.println("a= " + Client.a);
        System.out.println("b= " + Client.b);
    }
}

输出值:

a= 1
b= 1

思考:为什么两次输出的结果不同?

理论

类的初始化,本质上是执行类构造器<client>方法,Java 虚拟机会通过加锁来确保 <clinit> 方法仅被执行一次;

<client>方法是由编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。编译器收集的顺序是有语句在资源文件中出险的顺序所决定的。

解析

眼尖的小伙伴,肯定能看出来,private static Client client = new Client(); 的位置不同,才导致结果不同。

那为什么因为顺序不同,结果就不一样了么?如果你了解类的初始化过程就知道了!

我们拿案例1解析

首先,执行main方法的Client.getInstance(),因为这个类从来没有加载过,就会触发类的加载(上一篇:类的准备与解析,解释了会发生什么);

①此时解析的结果是:

client=null
a=0
b=0

解析之后,就是初始化了
执行到private static Client client = new Client()·时:
②结果是:

client=Client@1b4fb997
a=1
b=1

继续往下执行,到public static int b = 0;执行结束时,b被再次赋值,覆盖了之前的数据,a则没有再次赋值的操作所以就没有改变;
③此时结果是:

client=Client@1b4fb997
a=1
b=0

案例2 初始化过程与案例1相同,只是client初始话的顺序变了,然后②和③就交换了位置,以至变量b最后执行的操作是b++

总结

初始化顺序:

父类静态成员和静态代码块> 子类静态成员和静态代码块 > 父类普通成员和普通代码块 > 父类构造函数>子类普通成员和普通代码块>子类构造函数

`注意`:同样等级的代码按照代码从上至下的顺序执行。

在编写或梳理代码的时候要注意代码的顺序,以防程序最后的输出结果和我们的预期不一致。

相关文章

  • JVM系列之类的初始化

    类的初始化 前言 类孕育了新的生命周期,那么接下来就是让他健康的茁壮成长,对否? 案例1 输出值: 案例2 输出值...

  • JVM系列之类的加载

    一、前言 一处编译,处处运行! 二、JVM是什么? JDK包含了JRE,JRE是java程序的运行环境; JDK:...

  • JVM系列之类的验证

    一、前言 类的加载完成后,就是验证;保加载进来的字节流符合JVM规范 二、验证三问 1)什么是验证? 验证.c...

  • jvm系列之类加载机制

    muggle 1.类的生命周期    类从被加载到虚拟机内存中内存中开始,到卸载出内存为止,它的整个生命周期包括:...

  • JVM系列之类的使用与卸载

    前言 一个完整即将使用的类已经在JVM虚拟机中整装待发了,进击!!! 类的使用 类的使用一般可以分为主动使用和被动...

  • JVM系列之类的准备与解析

    一、前言 每个类的生命周期,和生命一样,都有起点与终点;每个类都会在自己的生命周期里,完成自己的使命--使命必达!...

  • 18家大厂Java面试题整理了350道(分布式+微服务+高并发)

    一、性能调优系列 1.Tomcat性能调优 JVM参数调优:-Xms 表示JVM初始化堆的大小,-Xmx 表示J...

  • Java类的初始化

    之前整理了《JVM之类加载机制》的文章,对于一个类的初始化阶段介绍太过简略,这里再开一篇文章,着重介绍类的初始化流...

  • JVM 之类加载

    一.概述 Java不同于C/C++这类传统的编译型语言,也不同于php这一类动态的脚本语言。可以说Java是一种半...

  • JVM介绍系列文章

    知晓JVM系列(一):对JVM总览知晓JVM系列(二):JVM内存管理机制与优化初探知晓JVM系列(三) :常用的...

网友评论

    本文标题:JVM系列之类的初始化

    本文链接:https://www.haomeiwen.com/subject/pjnahltx.html