Java对象初始化过程代码块与构造器调用顺序

Java中(静态)初始化块与构造方法执行顺序问题 阅读详情

前言

对Java对象初始化过程 代码块与构造器调用顺序进行整理说明。先说结论具体论证在下文。

代码加载的优先级顺序

静态代码块、静态成员变量->非静态代码块、非静态成员变量->new其他对象调用对应对象构造方法(在本地对象的方法外包括构造方法)->new本地对象调用构造方法。

【注意:若new对象时,该对象中有静态代码块和非静态代码块,每new一次对象,非静态代码块都会执行一次,但静态代码块只会执行一次往后new对象都不会再执行。】

构造方法的执行顺序

父类静态代码块(静态变量 > 静态块) > 子类的静态代码块 > 父类构造代码块、构造方法> 子类的构造代码块、构造方法

各种代码块的定义

静态代码块

class Demo{ static { //静态代码块...... } }

特点: 1、Java静态代码块中的代码会在类加载JVM时运行,且只被执行一次 2、静态块常用来执行类属性的初始化 ,和一些全局初始化的工作 3、静态块优先于各种代码块以及构造函数,如果一个类中有多个静态代码块,会按照书写顺序依次执行 4、静态代码块可以定义在类的任何地方中除了方法体中【这里的方法体是任何方法体】 5、静态代码块不能访问普通变量

有关静态代码块再详细介绍下:

静态代码块:在java中使用static关键字声明的代码块。静态块用于初始化类,为类的属性初始化。每个静态代码块只会执行一次。

由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行。 如果类中包含多个静态代码块,那么将按照"先定义的代码先执行,后定义的代码后执行"。 【注意:1 静态代码块不能存在于任何方法体内。2 静态代码块不能直接访问静态实例变量和实例方法,需要通过类的实例对象来访问。】 实例代码块 实例代码块 又叫 构造初始化块 , 构造代码块 , 初始化块 。

class Demo{ { //实例代码块...... } }

特点:

1、构造代码块在创建对象时被调用,每次创建对象都会调用一次
2、构造代码块优先于构造函数执行,同时构造代码块的运行依赖于构造函数
3、构造代码块在类中定义

局部代码块

局部代码块又叫 普通代码块 , 方法代码块

class Demo{ public void test(){ { //局部代码块...... } } }

特点: 1、普通代码块定义在方法体中 2、普通代码块与实例代码块的格式一致都是{} 3、普通代码块与构造代码块唯一能直接看出的区别是构造代码块是在类中定义的,而普通代码块是在方法体中定义的 4、可以限定变量生命周期,及早释放,提高内存利用率

验证各代码块的执行顺序

举例代码如下:

class Init {

    public Init() {
        System.out.println("无参构造器");
    }

    public Init(int a) {
        System.out.println("有参构造器");

    }

    {
        System.out.println("实例代码块1");
    }

    {
        System.out.println("实例代码块2");
    }

    {

        System.out.println("实例代码块3");
    }

    static {
        System.out.println("静态初始化块1");
    }

    static {
        System.out.println("静态初始化块2");
    }

    public void method(){
        {
            System.out.println("普通初始化块");
        }
    }
}

测试代码 如下:

class Demo {
    public static void main(String[] args) {
        Init init1 = new Init();
        init1.method();
        System.out.println("------------");
        Init init2 = new Init();
        init2.method();
        //多打印几个对象的目的是:方便看出Static静态代码块 是否只执行一次!!!
        System.out.println("------------");
        Init init3 = new Init();
        init3.method();
    }
}

运行结果如下图:

结论:

执行顺序为:静态代码块 > 实例代码块 > 构造函数 > 普通代码块,

且静态代码块,类加载的时候就会调用,且只调用一次(随着类的加载而执行)。

那么类什么时候会被加载呢?

  • 创建对象实例时(new)
  • 创建子类对象实例,父类也会被加载
  • 使用类的静态成员时(静态属性,静态方法)

验证存在继承关系中各代码块的执行顺序

举例继承关系为 Three——> Two——> One, 代码如下:

class One {

    public One() {
        System.out.println("One构造器");
    }

    {
        System.out.println("One实例化块");
    }

    static {
        System.out.println("One静态代码块");

    }

}

class Two extends One {

    public Two() {
        System.out.println("Two构造器");
    }

    {
        System.out.println("Two实例化块");
    }

    static {
        System.out.println("Two静态代码块");
    }

}

class Three extends Two {

    public Three() {
        System.out.println("Three构造器");
    }

    {
        System.out.println("Three实例化块");
    }

    static {
        System.out.println("Three静态代码块");
    }

}

//测试代码 如下:
public class Demo {
    public static void main(String[] args) {
        Three three = new Three();
        System.out.println("-----");
        Three three1 = new Three(); //重复执行的目的是为了 验证static是否只执行一次
        System.out.println("-----");
        Two three2 = new Three();   //验证 多态的情况下 用后面的类进行初始化 结果和上面一样
    }
}

根据执行结果可知,在多个类的继承中存在初始化块、静态初始化块、构造器,执行真实顺序为:先后执行父类A的静态块,父类B的静态块,最后子类的静态块,然后再执行父类A的实例代码块和构造器,然后是B类的实例代码块和构造器,最后执行子类C的实例代码块和构造器【注:这里的ABC对应One、Two、Three 】

结论:

多个类的继承中初始化块、静态初始化块、构造器的执行顺序为:

父类静态块——>子类静态块——>父类实例代码块——>父类构造器——>子类实例代码块——>子类构造器 ——>(如果有局部代码块, 再正常执行即可, 这里就没必要进行测试了)

通过字节码深究实例代码块优先于构造器原因

我们那一段代码作为例子说明下,代码如下:

class Init {

    public Init() {
        System.out.println("无参构造器");
    }

    public Init(int a) {
        System.out.println("有参构造器");

    }

    {
        System.out.println("实例代码块1");
    }

    {
        System.out.println("实例代码块2");
    }

    {
        System.out.println("实例代码块3");
    }

    static {
        System.out.println("静态初始化块1");
    }

    static {
        System.out.println("静态初始化块2");
    }

    public void method(){
        {
            System.out.println("普通初始化块");
        }
    }
}

接下来让我们看看 , Init.java编译完的的字节码文件(Init.class)

从这个字节码文件就可以很清晰的看出, 实例代码块实际上是被依次放到了构造方法的第一句, 所以可以的出此结论: 实例代码块的执行顺序是优先于构造器的。

Java-对象的操作(构造、初始化、封装)、static成员以及代码块 注意:一旦用户定义构造方法,编译器则不再生成。上述Date类中,没有定义任何构造方法,编译器会默认生成一个不带参数的构造方法。6.构造方法中,可以通过this调用其他构造方法来简化代码。注意:this(...)必须是构造方法中的第一条语句,不能形成环。public Date(){ //环this();7. 阅读详情

相关推荐

从光猫到机顶盒:H10G-13融合网关双系统网络配置全解析(含超密获取技巧)

本文详细解析了中国移动H10G-13融合网关的双系统网络配置,涵盖光猫路由与安卓电视盒子的协同工作。通过晶晨S905L3芯片的优化,设备实现高效网络接入与安卓9.0系统的定制化应用,特别适合酒店和民宿行业的智能化改造。文章还提供了超密获取技巧和线刷固件包的实用指南。

weixin_42525264的博客 944

Java对象初始化过程 代码块与构造器调用顺序

Java对象初始化过程 代码块与构造器调用顺序

RichardGeek的博客 1179

Kalibr标定避坑指南:如何用AprilGrid板快速完成双目IMU标定

本文详细介绍了使用AprilGrid板进行Kalibr双目IMU联合标定的实战技巧,包括标定工具选型、数据采集优化、标定流程及结果验证。通过AprilGrid板的唯一标识性和抗遮挡优势,结合IMU静止标定和运动激励设计,显著提升标定精度。文章还提供了常见报错处理和高级优化技巧,帮助开发者高效完成传感器标定。

sunny的博客 279

在 Java 中,类的属性、代码块、构造器和静态代码块的初始化顺序

子父类 静态属性、静态代码块, 构造器等执行顺序

weixin_43735471的博客 631

esp32-C3固件烧录用户手册

温馨提示:1.esp32-C3 BOOT脚为GPIO9,需要从芯片小板中焊接引出2.芯片小板中已经预留了所有烧录相关的引脚,大家可以按需焊接引线3.程序下载完,使用串口查看log时,需要使用220v供电使用(请务必准守用电安全)。原因:由于插座中包含继电器,计量计等耗电设备,所以usb转串口提供的3.3V电压和电流可能会出现供电不足,表现为usb转串口与电脑连接断断续续,导致无法查看log。

hbwang的博客 1万+

PSIM+PIL+CCS三剑客:手把手教你搞定DSP28335的软硬件联合调试

本文详细介绍了如何利用PSIM、PIL与CCS三款工具,实现DSP28335的软硬件联合调试。通过搭建兼容环境、从PSIM仿真生成PIL代码,再到实战联合调试与问题诊断,手把手指导开发者构建从虚拟模型到实际硬件的完整验证闭环,有效提升电力电子与电机驱动等领域的开发效率与可靠性。

weixin_29183637的博客 185

Java成员变量初始化和构造函数顺序

1、Java虚拟机会将所有的初始化动作手机到<init>()方法中,在分配内存后,就开始调用<init>()方法,其中,成员变量的初始化在构造函数里的初始化动作之前。 public class Test { private String s = "1"; public Test() { s = "2"; } public static void main(String[] args) { Test t = ne

诗人不写诗 2422

Zemax实现微透镜阵列光束整形(原理+仿真)

通过Zemax实现微透镜阵列的光场整形仿真。

VJCP_90909Bu0的博客 1万+

构造代码块、静态构造代码块和构造器执行顺序

构造代码块、静态构造代码块和构造器执行顺序 1.构造代码块 ​ 在java中一对{}就被称为代码块,写在类中的{}称为构造代码块,可用于初始化类属性,构造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行次序优先于类构造器。 public class CodeBlock { private int age; //构造代码块 { age = 12 ; //构造代码块的作用:初始化,先于构造器执行 System.out.println("构造代码块");

weixin_52235791的博客 444

基于simulink的电气弹簧ES稳压控制模型仿真

若要补偿母线电压的谐波,需控制ES上的谐波,即在单闭环母线电压有效值控制的基础上,增加谐波抑制环节来进行谐波控制,现有的各种检测和抑制谐波的方法有采用模拟滤波器、傅里叶分析进行谐波分析、基于瞬时无功功率理论的方法等。当关键负载ZC为电流源型非线性负载时,电路原理图如图7所示,由于电流源型非线性负载可以等效为谐波电流源,关键负载电流ic便会含有谐波分量,导致输电线电流is和母线电压VS同样会含有谐波分量,导致供电质量的严重下降,对用电设备的正常工作造成影响。分别为流过线路阻抗、非关键负载、关键负载的电流,

FPGA/MATLAB学习教程/源码/项目合作开发 1630

C#实战大华智能安防系统:从SDK封装到视频流与智能报警的全链路落地

本文将介绍C#集成大华SDK开发安防系统的实战经验,重点解决多路视频预览卡顿和报警延迟问题。文章通过三层架构设计(SDK封装层、业务服务层、应用层)实现解耦,详细分析线程安全封装、高效解码显示和智能事件联动等核心技术。针对16路摄像头同时预览时CPU占用率过高的问题,提出使用子码流拉流与异步解码的优化方案,并总结8个常见开发陷阱的解决方案。文中还提供了大华智能安防系统的完整架构图,展示从设备层到应用层的交互流程,特别强调业务服务层中视频流服务和智能报警服务的核心功能设计。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 427

子类与父类中静态代码块、匿名代码块、构造器的执行顺序

先看结论,执行顺序为 父类静态代码块-->>子类静态代码块-->>父类匿名代码块-->>父类构造器-->>子类匿名代码块-->>子类构造器 其中静态代码块在初始化时会被调用,但是匿名代码块与构造器只有在创建对象时才会调用。 上代码: 父类: public class InitSuper { static { ...

weixin_30722589的博客 105

FPGA实现DDR接口

verilog// DDR2控制器状态机// 初始化序列// 发出初始化命令endendendend// 自动预充电end// 其他状态...endcaseendend。

whm128的博客 998

java执行顺序

class Demo2{ static { System.out.println("I am demo2静态代码块"); } { System.out.println("I am demo2 属性"); } } class Demo{ static { System.out.println("static....."); } private static Dem...

Context 304

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

JAVA中的代码块以及继承关系中代码块和构造器的执行顺序

由于篇幅有限也为了方便理解,这里使用两个类的继承来讲解(

weixin_74141526的博客 872

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

java中类的初始化调用顺序

对象的初始化顺序: (1)加载父类(以下序号相同,表明初始化是按代码从上到下的顺序来的)   1.为父类的静态属性分配空间并赋于初值   1.执行父类静态初始化块; (2)加载子类   2.为子类的静态属性分配空间并赋于初值   2.执行子类的静态的内容; (3)加载父类构造器   3.初始化父类的非静态属性并赋于初值   3.执行父类的非静态

ysughw的专栏 686

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

java对象的初始化过程

class X{ Y y=new Y(); public X(){ System.out.print("X"); } } class Y{ public Y(){ System.out.print("Y"); } } public class Z extends X{ Y y=new Y(); public Z(){ System.out.print("Z"); } public static void main(String[] args) { new Z(); } }

weixin_45122172的博客 460

Java 属性赋值顺序

TL;DR 默认初始化; 显示初始化/代码块中赋值 构造器中初始化 对象.属性或对象.方法 代码 Grandfather 类: package com.mindartisan.priority; public class Grandfather { static { System.out.println("爷爷的静态代码块"); } { System.out.println("爷爷的普通代码块"); } public Grandf

格物致知,知行合一。 500

Java中的代码块

本文详细解释了代码块的概念与使用,并深入解释了创建一个对象时的底层流程分析,非常非常重要,希望小伙伴们看后能有所收获!最后,如果本文有什么错漏的地方,欢迎大家批评指正!一起加油!!我们下一篇博文见吧!

林二月的博客 1077

类的初始化和实例的初始化

有如下两个类 Father (父类) package com.yzx.test01; /** * 父类对象 *父类初始化<client> *(1) j=method();(5) *(2) 父类的静态代码块(1) * * 父类的实例化方法: * (1)super() (最前) * (2)i=test(); * (3)父类的非静态代码块 * (4)父类的无参构...

但行好事莫问前程 546

通过字节码深入了解创建对象的过程

package shixun.test; public class Test2643 { public static void main(String[] args) { Person person = new Person(); } } class Tag { int i; public Tag(int i) { this.i = i; //System.out.println("Tag(" + this.i + ")"); } } class Person { Tag t

qq_46097639的博客 426

java初始化new_new一个对象的初始化过程

云原生敏捷运维从入门到精通it服务69元包邮(需用券)去购买 >###############################今天总结一下,new对象的初始化过程。###############################首先,当不含static成员时,先看一下案例图:如图所示,我们先定义相关类,Building,House(继承Building),Villa(继承House),同时,H...

weixin_39780260的博客 980

java普通代码块,静态代码块和构造器在实例化时执行顺序

测试代码: public class test4 { { System.out.println(1); } static { System.out.println(2); } test4() { System.out.println("构造器"); } { System...

sin_404的博客 418
上一篇: 不懂分布式系统概念没关系,这份足足《800页分布式系统概念》啃完不信你还不懂!
下一篇: 聊聊RocketMQ Rebalance负载均衡触发机制浅析
Java_ttcd
博客等级 码龄4年 198粉丝 190原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值