【Java】Java中类的初始化顺序(静态方法,静态块,非静态块,最后有流程图)
📝个人主页:哈__
期待您的关注
目录
一、无继承关系类的初始化
1、静态变量k被初始化
2、静态变量t1初始化
3、静态变量 t2初始化
4、静态变量i初始化
5、静态变量n初始化
6、静态块初始化
7、非静态块初始化
8、非静态属性初始化
9、执行构造方法
二、有父类继承的初始化
在日常使用Java的时候,我们都接触过new这个关键字,那你是否知道在我们的对象真正创建出来之前都做了哪些事情呢?
实际上要去判断一个类的初始化的顺序,需要分一下情况,一种是没有继承关系的类(不考虑Object类),一种是有继承关系的类。
一、无继承关系类的初始化
先看下边的代码。有着这样的一个类InitializeDemo ,我们直接运行main方法,你知道会打印出来什么吗?
public class InitializeDemo {private static int k = 1;private static InitializeDemo t1 = new InitializeDemo("t1");private static InitializeDemo t2 = new InitializeDemo("t2");private static int i = print("i");private static int n = 99;{print("初始化块");j=100;}public InitializeDemo(String str){System.out.println((k++)+":" + str + " i="+i+". n="+n);++i;++n;}static{print("静态块");n=100;}private int j = print("j");public static int print(String str){System.out.println((k++)+":" + str + " i="+i+". n="+n);++n;return ++i;}public static void main(String[] args) {InitializeDemo i = new InitializeDemo("test");}
}
打印结果如下所示。
想要弄明白这个,我就得先了解一下类的生命周期了。我们通过主方法运行Java程序,而这个主方法中创建了i对象并且属于InitializeDemo 类,所以在main方法执行时会将我们的类进行初始化。
在我们的类第一次进行初始化的时候,我们类中的静态块和静态属性会被优先构建。之后才轮得到非静态块和非静态属性。
当你知道了上边的规则之后,我们来看代码,类中有五个静态属性,一个非静态属性,一个静态块,一个非静态块还有一个静态方法。我们优先构建静态方法、属性和静态块,之后在构建非静态块。
这里我总结出第一条规则。
类的一个对象进行初始化,按照代码顺序从上往下先构建静态的属性、方法和静态块,之后在构建非静态块和非静态属性。(类中的静态块和静态变量只会初始化一次,也就是类第一次被用到的时候)
1、静态变量k被初始化
private static int k = 1;
2、静态变量t1初始化
private static InitializeDemo t1 = new InitializeDemo("t1");
这里还要说一下,这个静态变量是创建自己的类的对象,代码执行到这一行就要进行一个对象的初始化过程了。遇到这种创建本类对象的,我们按照以下的第二条规则。
一个类中有静态的本类对象,创建的过程从上到下先执行本类的非静态块和非静态属性,最后在执行构造方法。
那么我们初始化t1的时候,就要从上向下找非静态块和非静态属性(如果有的话 ),最后在执行构造方法。
{print("初始化块");j=100;}
我们调用print函数并且将j的值修改为100,这样就出现了我们的第一行。
之后往下走,走到了这一行代码。这行代码定义了j变量,并且调用了print方法,所以也就有了我们的第二行。
private int j = print("j");
最后调用构造方法。打印我们的第三行。
现在你是否清楚了前三行输出结果是怎么来的了吗?这前三行的结果都是t1进行初始化时非静态块和非静态变量的执行结果。
3、静态变量 t2初始化
搞明白了t1是如何初始化的t2就和t1一模一样了,这里不讲解。
4、静态变量i初始化
静态变量i的初始化用到了print函数,这也就是第七行为什么会打印的原因。
private static int i = print("i");
5、静态变量n初始化
private static int n = 99;
6、静态块初始化
这里调用print函数,也就是第八行的由来。
static{print("静态块");n=100;}
ok,到了这一步我们的静态属性和静态块已经从上到下全部初始化完成了。但你要知道,我们在上边初始化的非静态块和非静态属性所打印的语句是我们的t1和t2对象引起的,并非我们主方法内构建的i对象引起的,接下来还要初始化我们的非静态块和属性。
7、非静态块初始化
第九行的由来。
{print("初始化块");j=100;}
8、非静态属性初始化
第十行的由来。
private int j = print("j");
9、执行构造方法
第十一行的由来。
public InitializeDemo(String str){System.out.println((k++)+":" + str + " i="+i+". n="+n);++i;++n;}
以上就是我们的一个类的构建过程,这里我给大家一张图(自己画的)。
这里需要注意以下,非静态属性如果创建的是自己的本类对象的话,那么会报错的。原理也很简单,就是一个循环创建的过程导致栈溢出。
二、有父类继承的初始化
和没有父类继承初始化大同小异,我定义了这样的一个类让InitializeDemo,去继承。为了便于还是懵懂的同学理解,我把静态变量t1和t2删掉。
public class InitializeDemoFather {{System.out.println("父类初始化块");}static{System.out.println("父类静态块");}public InitializeDemoFather(){System.out.println("父类构造函数");}
}
来看看我们现在的打印结果。
我给大家讲一下初始化的顺序大家就明白了,这里用一张图来表示。
对应着上边的图,是不是一看就有点思路了呢?
如果你可以完整的走出以上的输出顺序,你就可以把t1和t2对象加上去了,不过不要被输出顺序所迷惑,就比如说,你可能会看到父类静态块和属性初始化完成后,初始化的不是子类的静态块和静态属性,而是父类的非静态块和非静态属性。你应该认真的思考一下,这个 输出的父类的非静态块和非静态属性初始化的语句到底是从何而来?
相关文章:

【Java】Java中类的初始化顺序(静态方法,静态块,非静态块,最后有流程图)
📝个人主页:哈__ 期待您的关注 目录 一、无继承关系类的初始化 1、静态变量k被初始化 2、静态变量t1初始化 3、静态变量 t2初始化 4、静态变量i初始化 5、静态变量n初始化 6、静态块初始化 7、非静态块初始化 8、非静态属性初始化 9、执行构造…...

在RK3588开发板使用FFMpeg 结合云服务器加SRS实现摄像头数据推流到云端拱其他设备查看
今天测试了一把在开发板把摄像头数据推流到云端服务器,然后给其他电脑通过val软件拉取显示摄像头画面,浅浅记录一下大概步骤 1.开发板端先下载ffmpeg apt install ffmpeg2.云服务器先安装SRS的库 云服务器我使用ubuntu系统,SRS是个什么东西&…...
elasticsearch搭建教程
主要参看这里就行,需要特别注意其中报错的解决方案:搭建elasticsearch 单机节点里,按照上述教程搭建只能开放本地访问,如果需要其他机器访问,需要在elasticsearch.yml里新增几个配置: node.name: node-1 network.host…...

c++ 归并排序
归并排序是一种遵循分而治之方法的排序算法。它的工作原理是递归地将输入数组划分为较小的子数组并对这些子数组进行排序,然后将它们合并在一起以获得排序后的数组。 简单来说,归并排序的过程就是将数组分成两半,对每一半进行排序,…...

基于vs和C#的WPF应用之动画3
注:1、在内部和外部使用缓动函数 <Grid.Resources> <PowerEase x:Key"powerease" Power"3" EasingMode"EaseInOut"/> </Grid.Resources> <DoubleAnimation EasingFunction"{StaticResource powerease}&quo…...

Python import 必看技巧:打造干净利落的代码结构
大家好,学习Python你肯定绕不过一个概念import,它是连接不同模块的桥梁,是实现代码复用和模块化的关键。本文将带你深入探索Python中import的原理,并分享一些实用的导入技巧。 1. import 原理 导入机制概述 在Python中,模块(module)是一种封装Python代码的方式,它允许…...
计算机视觉(CV)(Computer Vision)
计算机视觉技术(Computer Vision),解决的是什么? 图片和视频是非结构化数据,机器如果要理解某一图片或视频表达的内容,是无法直接分析的,这种情况,就需要有计算机视觉技术ÿ…...

python:画折线图
import pandas as pd import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties# 设置新宋体字体的路径 font_path D:/reportlab/simsun/simsun.ttf# 加载新宋体字体 prop FontProperties(fnamefont_path)""" # 读取 xlsx 文件 d…...
Spring Data JPA 与 MyBatisPlus的比较
前言 JPA(Java Persistence API)和MyBatis Plus是两种不同的持久化框架,它们具有不同的特点和适用场景。 JPA是Java官方的持久化规范,它提供了一种基于对象的编程模型,可以通过注解或XML配置来实现对象与数据库的映射…...

【C++】STL-list的使用
目录 1、list的使用 1.1 list的构造 1.2 list的遍历 1.3 list capacity 1.4 list element access 1.5 容量相关 list是一个带头双向循环链表 1、list的使用 1.1 list的构造 1.2 list的遍历 list只有两种遍历方式,因为没有operator[] 因为list的双向链表&am…...
进度条(小程序)
缓冲区的概念 缓冲区是内存中的一个临时存储区域,用来存放输入或输出数据。在标准 I/O 库中,缓冲区的使用可以提高数据处理的效率。例如,当向终端输出文本时,字符通常存储在缓冲区中,直到缓冲区满或者遇到特定条件时才…...

PyCharm安装教程(超详细图文教程)
一、下载和安装 1.进入PyCharm官方下载,官网下载地址: https://www.jetbrains.com/pycharm/download/ 专业版安装插件放网盘了,网盘下载即可:itcxy.xyz/229.html2.安装 1.下载后找到PyCharm安装包,然后双击双击.ex…...

金蝶BI应收分析报表:关于应收,这样分析
这是一张出自奥威-金蝶BI方案的BI应收分析报表,是一张综合运用了筛选、内存计算等智能分析功能以及数据可视化图表打造而成的BI数据可视化分析报表,可以让企业运用决策层快速知道应收账款有多少?账龄如何?周转情况如何?…...

salmon使用体验
文章目录 salmon转录本定量brief模式一:fastq作为输入文件需要特别注意得地方 模式二: bam文件作为输入 salmon转录本定量 brief 第一点是,通常说的转录组分析其中有一项是转录本定量,这是一个很trick的说话,说成定量…...
Ubuntu 20.04 安装 Ansible
使用官方的 Ubuntu PPA 更新包列表: apt update安装软件属性常用命令 apt install software-properties-common添加 Ansible PPA 到系统: add-apt-repository --yes --update ppa:ansible/ansible再次更新包列表以包括新添加的 PPA: apt …...
TypeScript学习笔记:强类型JavaScript的优雅之旅
在前端开发领域,JavaScript以其灵活性和广泛的支持度成为无可争议的王者。然而,随着项目规模的增长,JavaScript的动态类型特性开始暴露出一些问题,比如代码的可维护性、类型错误难以提前发现等。为了解决这些问题,Micr…...

监控异地组网怎么组网?
监控异地组网是指在不同地域的网络环境下,实现对监控设备的远程访问和管理。在传统的网络环境下,由于网络限制和设备配置等问题,监控设备的远程访问往往受到一定的限制和困扰。为了解决这个问题,引入了天联组网技术,实…...

将本地托管模型与 Elastic AI Assistant 结合使用的好处
作者:来自 Elastic James Spiteri, Dhrumil Patel 当今公共部门组织利用生成式人工智能解决安全挑战的一种方式。 凭借其筛选大量数据以发现异常模式的能力,生成式人工智能现在在帮助团队保护其组织免受网络威胁方面发挥着关键作用。 它还可以帮助安全专…...
Linux的内核态和用户态
一、Linux操作系统运行在两种不同的运行模式下:内核态(Kernel Mode)和用户态(User Mode) 内核态(Kernel Mode): 内核态也称为特权模式或系统模式,是操作系统内核执行代码…...
springboot利用Redis的Geo数据类型,获取附近店铺的坐标位置和距离列表
文章目录 GEO介绍GEO命令行应用添加地理坐标位置获取指定单位半径的全部地理位置列表springboot 的实际应用 GEO介绍 在Redis 3.2版本中,新增了一种数据类型:GEO,它主要用于存储地理位置信息,并对存储的信息进行操作。 GEO实际上…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...