今天你的静态变量和静态代码块执行了吗?
摘要:今天你的静态变量和静态代码块执行了吗?
本文分享自华为云社区《【java】静态变量和静态代码块那些事》,作者: 大金(内蒙的)。
今日题目:
今天你的静态变量和静态代码块执行了吗?
话不多说,开始今天的题目讲解吧。
先介绍个常识:
静态成员属性的初始化早于静态代码块;
静态代码块是指的类的初始化操作,初始化早于对象的创建;
类静态域的只会初始化一次。
题目一:输出啥?
class Father{ public static int m = 33; static{ System.out.println("父类被初始化"); } } class Child extends Father{ static{ System.out.println("子类被初始化"); } } class StaticTest{ public static void main(String[] args){ System.out.println(Child.m); System.out.println(new Child()); } }
答案:
父类被初始化
33
子类被初始化
Child1@2781e022
题目二:输出啥?
class Const{ public static final String NAME = "我是常量"; static{ System.out.println("初始化Const类"); } } public class FinalTest{ public static void main(String[] args){ System.out.println(Const.NAME); } }
答案:我是常量
详细说明:
static final的变量是在类加载的准备阶段(还没有到初始化):
为类的静态变量分配内存,并将其赋默认值
对于该阶段有以下几点需要注意:
- 只对static修饰的静态变量进行内存分配、赋默认值(如0、0L、null、false等)。
- 对static final的静态字面值常量直接赋初值(赋初值不是赋默认值)。
题目三:输出啥?
class Const{ static{ System.out.println("初始化Const类"); } } public class ArrayTest{ public static void main(String[] args){ Const[] con = new Const[5]; } }
输出:空
题目四:输出啥?
class Other { public static Other o1 = new Other(); public static Other o2 = new Other(); { System.out.println("构造块"); } static { System.out.println("静态块"); } public static void main(String[] args) { Other other = new Other(); } }
答案:
构造块
构造块
静态块
构造块
脑瓜子是不是嗡嗡的!!!
下面介绍一下,类加载过程,帮你debug下。
类加载分为以下步骤:
整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。
- 加载:二进制.class文件各种文件加载一遍,类加载器去加载的
- 验证:验证类的正确性,像是格式啊、方法重写啥的啊
- 准备:静态域的初始化赋值,这个是给个默认值啊。
- 解析:符号引用(编程原理)解析为直接引用。
- 初始化:静态域的代码里面赋值。
初始化过程,就是常识中的静态域加载的过程。
以下四种情况触发。
- 遇到new、getstatic、putstatic、invokestatic这四条字节码指令时,如果类还没有进行过初始化,则需要先触发其初始化。生成这四条指令最常见的Java代码场景是:使用new关键字实例化对象时、读取或设置一个类的静态字段(static)时(被static修饰又被final修饰的,已在编译期把结果放入常量池的静态字段除外)、以及调用一个类的静态方法时。
- 使用Java.lang.refect包的方法对类进行反射调用时,如果类还没有进行过初始化,则需要先触发其初始化。
- 当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
- 当虚拟机启动时,用户需要指定一个要执行的主类,虚拟机会先执行该主类。
除了上面四种情况,有几种特殊情况。类的初始化会被动加载。
- 通过子类引用父类中的静态字段,这时对子类的引用为被动引用,因此不会初始化子类,只会初始化父类。
- 常量在编译阶段会存入调用它的类的常量池中,本质上没有直接引用到定义该常量的类,因此不会触发定义常量的类的初始化。这里实际上完成了“准备”阶段。
- 通过数组定义来引用类,不会触发类的“初始化”。
再看一遍题目:
所以,结合常识:
静态成员变量的初始化早于静态代码块;
静态代码块是指的类的初始化操作,初始化早于对象的创建;
类静态域的只会初始化一次。
再看一遍上面的代码,是不是能得出答案了呢?

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Swift在58安居客房产实践
01 背景 2014年Apple在WWDC发布了新的语言Swift。随后一直在不断的更新迭代和优化,国内外各大公司一直在踊跃欲试,但一直都没有商用或大规模使用。直到2019年Apple发布了5.0版本,并宣布ABI稳定,2020年更是陆续SwiftUI、CareKit等Swift专属SDK,并且Apple一直在大力推广鼓励大家使用Swift。在这样的背景下,越来越多的开发者、开源项目都加快了Swift生态搭建的脚步。另外Swift作为一门新语言,相比于Objective-C有巨大的后发优势:安全、高效、高性能等。这些特性有利于开发者提升开发效率和APP质量。在《Swift 2021 生态调研报告》中App Store免费前100中国外APP使用Swift占比91%。国内占比近50% 02 现 状 在这样的趋势之下,58集团与2020年底启动了Swift共建项目,内部称为混天项目。目标是搭建Swift的基础组件、辅助工具及基础设施。制定集团Swift开发规范和代码检测工具以及Swift在各个业务线中的落地。 房产业务作为集团核心产业,深度参与了混天项目的研发及Swift的落地。下面的内容...
- 下一篇
10个问题让你快速避开java中的jdbc常见坑
摘要:JDBC,即Java Database Connectivity,java数据库连接。是一种用于执行SQL语句的Java API,它是Java中的数据库连接规范。 本文分享自华为云社区《10个问题让你快速避开java中的jdbc常见坑》,作者: breakDraw。 Connection.setAutoCommit(boolean) 用于事务提交。 setAutoCommit(true), 则执行的所有sql执行都会作为单个事务直接提交并运行 setAutoCommit(false), 则必须等调用conn.commit()才会提交运行 Q: setAutoCommit默认是true还是false A: 默认是true。 Q: setAutoCommit(true)的缺点是什么? A: 如果一次性执行多个sql语句, 中间sql出错时,就会造成脏数据。 Q: setAutoCommit(false)后,如果出了错却没有在catch中进行Connection的rollBack操作,会发生什么? A; 操作的表就会被锁住,造成数据库死锁 fetchSize fetchSize 是设定...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7,CentOS8安装Elasticsearch6.8.6