java中类的普通初始化块一定在静态初始化块后运行吗
大部分教程都会告诉我们静态初始化块和静态字段总是在初始化块和普通类字段前运行,事实上也确实如此,直到我看到下面这样的代码:
public class Test {
static Test test = new Test();
{
System.out.println("normal");
}
static{
System.out.println("static");
}
public static void main(String [] args){
Test test = new Test();
}
}
可以先猜一猜结果,然后我们编译运行:
$ javac Test.java
$ java Test
normal
static
normal
难道不应该是先打印出static才对吗?这里我就不卖关子了,答案很简单。我们先来看一段话:
every constructor written in the Java programming language (JLS §8.8) appears as an instance initialization method that has the special name <init>. The initialization method of a class or interface has the special name <clinit>.
这段话来自jls,意思是普通的构造函数和初始化块会被放在一个叫<init>的方法里,在创建对象实例时调用;而类自身的初始化包括静态字段和静态方法会被放在叫<clinit>的方法里。而静态字段和静态块的初始化优先级相同,顺序遵从在代码中排列的顺序,也就是谁在前面谁先执行。
因此执行顺序已经明了了:
- 因为main函数中要创建类的实例,所以类会先被加载,这是调用了
<clinit> - 静态字段在静态初始化块之前,所以先执行初始化
- 静态字段调用了
new Test()创建类的实例,这时调用了<init> - 因为普通的初始化块在
<init>里,所以被调用,首先打印出了normal - 静态字段初始化完成后开始执行紧随其后的静态块,打印出static
- 随后回到main函数中,类的初始化只会运行一次,所以这次只有
<init>运行,打印出normal
因此看起来像是普通初始化块在静态块之前运行了,实际上只是静态字段的初始化导致了普通初始化块的提前执行。
知道了原理后,想下面这样的代码会输出什么自然也不在话下了:
public class Init {
private int v = 0;
static Init obj2 = new Init(); // 只能是static字段,想一想为什么
static {
System.out.println("static 2");
}
static Init obj1 = new Init();
{
System.out.println("from init");
}
static {
System.out.println("static 1");
}
public static void main(String[] args) {
var o1 = new Init();
var o2 = new Init();
}
}
当然,在实际的编码中静态块应该只负责静态字段的处理,普通的初始化块只负责对普通类字段的处理,上面的代码是不应该被模仿的。
参考
https://www.zhihu.com/question/50374553
java中类的普通初始化块一定在静态初始化块后运行吗的更多相关文章
- Java学习笔记11---静态成员变量、静态代码块、成员变量及构造方法的初始化或调用顺序
当创建一个对象时,各种成员变量及构造方法的初始化或调用顺序是怎样的呢? (1).如果类尚未加载,则先初始化静态成员变量和静态代码块,再初始化成员变量,最后调用相应的构造方法: (2).如果类已经加载过 ...
- JAVA程序执行顺序(静态代码块》非静态代码块》静态方法》构造函数)
总结:静态代码块总是最先执行. 非静态代码块跟非静态方法一样,跟对象有关.只不过非静态代码块在构造函数之前执行. 父类非静态代码块.构造函数执行完毕后(相当于父类对象初始化完成), 才开始执行子类的非 ...
- java中静态代码块,非静态代码块,构造函数
关于静态代码块 静态代码块的写法: static { System.out.println("我是静态代码块"); } 静态代码块的特点: 1.执行优先级高于非静态的初始化块,它会 ...
- Java子父类间静态代码块、非静态代码块、构造方法的执行顺序
子类A继承父类B,A a=new A(); 正确的执行顺序是:父类B静态代码块->子类A静态代码块->父类B非静态代码块->父类B构造函数->子类A非静态代码块->子类A ...
- java 对象的初始化流程(静态成员、静态代码块、普通代码块、构造方法)
一.java对象初始化过程 第一步,加载该类,一个java对象在初始化前会进行类加载,在JVM中生成Class对象.加载一个类会进行如下操作,下面给出递归描述.(关于Class对象详见反射 点击这里) ...
- Java中静态变量、静态代码块、非静态代码块以及静态方法的加载顺序
在研究单例设计模式的时候,用到了静态变量和静态方法的内容,出于兴趣,这里简单了解一下这四个模块在类初始化的时候的加载顺序. 经过研究发现,它们的加载顺序为: 1.非静态代码块 2.静态变量或者静态代码 ...
- 浅谈Java中静态代码块和非静态代码块
静态代码块: static{} 执行优先级高于非静态的初始化块,它会在类初始化(类初始化这个问题改天再详细讨论)的时候执行一次,执行完成便销毁,它仅能初始化类变量,即static修饰的数据成员. 非静 ...
- Java静态代码块与非静态代码块
静态代码块,格式是 static{ },随着类的加载而加载,且只执行一次. 在程序中,执行的优先级最高. 非静态代码块,格式是{ },在创建对象的时候运行(即new一个对象的时候),每创建一次对象就执 ...
- Java的初始化块、静态初始化块、构造函数的执行顺序及用途探究
Java与C++有一个不同之处在于,Java不但有构造函数,还有一个”初始化块“(Initialization Block)的概念.下面探究一下它的执行顺序与可能的用途. 执行顺序 首先定义A, B, ...
- Java提高篇——静态代码块、构造代码块、构造函数以及Java类初始化顺序
静态代码块:用staitc声明,jvm加载类时执行,仅执行一次构造代码块:类中直接用{}定义,每一次创建对象时执行.执行顺序优先级:静态块,main(),构造块,构造方法. 构造函数 public H ...
随机推荐
- srm-50
刚开始拿到题目没有思路,看了字符串发现也没什么特别的,也没有提示输入什么什么,然后找到main函数,f5进去以后也没什么特别的 然后就看了wp发现得从程序本身出发去解决问题 点开程序,随便输入点什么 ...
- Vue07-Axios
Axios axios是一个网络请求相关的库. axios: ajax i/o system 使用axios编写的网络请求代码,可以运行在浏览器端,也可以在Node环境中运行. 01. 支持的请求方式 ...
- MNIST中文手写数字数据识别
MNIST中文手写数字数据识别 实验环境 python=3.7 torch==1.13.1+cu117 torchaudio==0.13.1+cu117 torchvision==0.14.1 数据描 ...
- 基于Redis的简易延时队列
基于Redis的简易延时队列 一.背景 在实际的业务场景中,经常会遇到需要延时处理的业务,比如订单超时未支付,需要取消订单,或者是用户注册后,需要在一段时间内激活账号,否则账号失效等等.这些业务场景都 ...
- 【论文阅读】HTTP 流量和恶意 URL 的异常检测
Part 1关于论文 基本信息 题目:HTTP 流量和恶意 URL 的异常检测 源码:sec2vec源代码 摘要 在本文中,我们将展示如何利用自然语言处理(NLP)中已知 的方法来检测 HTTP 请求 ...
- ubuntu安装opencv的正确方法
本文介绍的是如何安装ubuntu下C++接口的opencv 1.安装准备: 1.1安装cmake sudo apt-get install cmake 1.2依赖环境 sudo apt-get ins ...
- 微服务项目-小Q视频网
1.后台管理系统(更新中...) (1)讲师列表 (2)添加讲师 (3)导入课程分类 (4)课程分类列表 其他功能就不一一截图了,后台详细功能如下 2.前台会员系统(更新中...) (1)前台的技术栈 ...
- 【fmjava】 面试题突击训练-Java基础语法篇01
JDK 和 JRE 有什么区别? JDK:Java Development Kit 的简称, Java 开发工具包, 提供了 Java 的开发环境和运行环境. JRE:Java Runtime Env ...
- intel 虚拟化 VT-d VT-x VT-c 的区别
intel 虚拟化 VT-d VT-x VT-c 有什么区别,各是什么意思,有什么作用 简单描述理解 VT-d VT-x VT-c VT-d 英文全程为 Virtualization Technolo ...
- Guava常用工具类总结
=== -"我想写得更优雅,可是没人告诉我怎么写得更优雅" -"Null的含糊语义让人很不舒服.Null很少可以明确地表示某种语义,例如,Map.get(key)返回Nu ...