Java执行顺序大揭秘:静态块、非静态块和构造方法谁先谁后?

简介: 本文详细介绍了Java中的初始化块,包括静态初始化块和非静态初始化块的概念、执行顺序和实际应用场景。通过具体示例,帮助读者理解这两种初始化块的区别和使用场景,让面试官对你刮目相看。



Hello大家好,我是小米!今天咱们来聊聊Java中的一个小而重要的知识点——初始化块。可能有的小伙伴一听这名字就觉得有点头大,这东西到底是干嘛的?为啥面试官总爱问它?别急,今天我会带大家从原理到实战,一次性搞懂静态初始化块和非静态初始化块的执行顺序、优先级和用法,让面试官忍不住点头!

什么是初始化块?

在Java中,初始化块(Initialization Block)是一段可以在类中定义的代码,用于在创建对象时执行某些特定的操作。根据是否带有static关键字,可以分为:

  • 静态初始化块(Static Initialization Block):用static关键字声明,只会在类加载时执行一次。
  • 非静态初始化块(Instance Initialization Block):没有static关键字,每次创建对象时都会执行。

先别急着觉得难,初始化块其实是Java中比较常见的用法,尤其是在需要初始化一些复杂的逻辑或共享资源时非常方便。我们从头开始了解它们的执行顺序和用法!

静态初始化块:优先级最高的初始化块

1. 静态初始化块是什么?

静态初始化块,是由static关键字修饰的一段代码。它的特性有:

  • 只执行一次:因为它是在类加载时执行的,所以整个类生命周期中只会执行一次。
  • 优先级最高:静态初始化块是类第一次加载时最先执行的,甚至在main方法之前。
  • 共享性强:由于它只执行一次,所以适合用来初始化类级别的资源,比如静态变量。

我们来看一个简单的例子:

运行这段代码,你会看到输出结果为:

看到没?静态初始化块在main方法之前执行!这是因为Java在执行代码前,必须先加载类,而静态初始化块在类加载时就会执行,这也就是为什么它的优先级最高

2. 静态初始化块的实际应用场景

静态初始化块通常用于初始化一些需要在类加载时完成的逻辑,比如:

  • 静态变量的初始化:在块中对静态变量进行一些复杂的计算或逻辑操作。
  • 初始化共享资源:比如数据库连接池、文件资源等,这些资源只需要创建一次即可共享。

例如,假设我们有一个数据库连接池:

在这个例子中,数据库连接只需要创建一次,这样可以确保每次调用getConnection时都能拿到已经初始化好的连接。

非静态初始化块:每次创建对象时执行

接下来我们说说非静态初始化块。它没有static关键字,每次创建对象时都会被调用。非静态初始化块的执行顺序是在构造方法之前,但在静态初始化块之后。

1. 非静态初始化块是什么?

非静态初始化块和静态初始化块的区别在于:

  • 每次创建对象时都会执行:只要你new一个对象,非静态初始化块就会执行一次。
  • 优先级低于静态初始化块:静态块会最先执行,接着才是非静态块。

来看下面的例子:

输出结果为:

这里可以看到执行顺序是:

  1. 静态初始化块
  2. main方法开始
  3. 非静态初始化块
  4. 构造方法
  5. main方法结束

2. 非静态初始化块的实际应用场景

非静态初始化块通常用来初始化实例变量,或者是对对象进行一些准备操作。比如:

运行这段代码会输出:

每创建一个User对象,非静态初始化块都会执行一次,用于初始化默认的age属性,这样每个对象的age值都默认是18。

总结一下执行顺序

到这里,我们对静态初始化块和非静态初始化块的执行顺序已经有了清晰的了解,最终的执行顺序如下:

  • 静态初始化块:在类加载时执行,只执行一次。
  • 非静态初始化块:在对象创建时执行,每次创建对象都会执行。
  • 构造方法:紧随非静态初始化块之后,构造方法会执行。

我们可以用这张图来帮助记忆:

什么时候用静态初始化块和非静态初始化块?

静态初始化块

  • 适用于需要类级别的初始化逻辑,比如初始化静态变量、共享资源。
  • 执行一次的操作,可以放在静态初始化块中,确保不会重复执行。

非静态初始化块

  • 适用于对象级别的初始化逻辑,比如初始化实例变量。
  • 每次创建对象都要执行的操作,可以放在非静态初始化块中。

END

好了!今天的初始化块总结到这里啦!希望大家可以通过这篇文章,彻底搞懂静态初始化块和非静态初始化块的区别以及实际应用。如果大家在面试时遇到类似问题,不妨用今天学到的知识点去回答,相信会给面试官留下深刻的印象!

有啥不懂的地方,欢迎在评论区留言~ 我是小米,我们下次再见,拜拜!

我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号软件求生,获取更多技术干货!

相关文章
|
20天前
|
设计模式 Java 测试技术
Java零基础-构造方法详解
【10月更文挑战第5天】Java零基础教学篇,手把手实践教学!
12 1
|
29天前
|
Java
java构造方法时对象初始化,实例化,参数赋值
java构造方法时对象初始化,实例化,参数赋值
42 1
|
2月前
|
Java API
java调用构造方法
java调用构造方法
37 3
|
29天前
|
Java
java构造方法的两种传值调用对实参的影响
java构造方法的两种传值调用对实参的影响
26 0
|
30天前
|
Java 程序员 编译器
【Java】继承、super、final、子类构造方法
【Java】继承、super、final、子类构造方法
26 0
|
3月前
|
Java
【Java基础面试十九】、构造方法能不能重写?
这篇文章指出Java中的构造方法不能被重写,因为构造方法必须与类名相同,而重写要求子类方法与父类方法同名,允许构造方法重写将违背这一规则。
【Java基础面试十九】、构造方法能不能重写?
|
3月前
|
Java 数据安全/隐私保护
Java代码的执行顺序和构造方法
构造方法是类的一种特殊方法,用于初始化新对象。在 Java 中,每个类默认都有一个与类名同名的构造方法,无需返回类型。构造方法不能用 static、final、synchronized、abstract 或 native 修饰。它可以重载,通过不同的参数列表实现多种初始化方式。构造方法在对象实例化时自动调用,若未显式声明,默认提供一个无参构造方法。构造代码块和静态代码块分别用于对象和类的初始化,按特定顺序执行。
29 0
|
3月前
|
Java 编译器 数据库连接
Java中的无参数构造方法
Java中的无参数构造方法
|
8天前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
79 38
|
5天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?