java中类的普通初始化块一定在静态初始化块后运行吗
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java中类的普通初始化块一定在静态初始化块后运行吗,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2003字,纯文字阅读大概需要3分钟。
内容图文
大部分教程都会告诉我们静态初始化块和静态字段总是在初始化块和普通类字段前运行,事实上也确实如此,直到我看到下面这样的代码:
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中类的普通初始化块一定在静态初始化块后运行吗所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。