可能有的小伙伴一听这名字就觉得有点头大,这东西到底是干嘛的?为啥面试官总爱问它?别急,今天我会带大家从原理到实战,一次性搞懂静态初始化块和非静态初始化块的执行顺序、优先级和用法,让面试官忍不住点头!
什么是初始化块?
在Java中,初始化块(Initialization Block)是一段可以在类中定义的代码,用于在创建对象时执行某些特定的操作。根据是否带有static关键字,可以分为:
静态初始化块(Static Initialization Block):用static关键字声明,只会在类加载时执行一次。
非静态初始化块(Instance Initialization Block):没有static关键字,每次创建对象时都会执行。
先别急着觉得难,初始化块其实是Java中比较常见的用法,尤其是在需要初始化一些复杂的逻辑或共享资源时非常方便。我们从头开始了解它们的执行顺序和用法!
静态初始化块:优先级最高的初始化块
1. 静态初始化块是什么?
静态初始化块,是由static关键字修饰的一段代码。它的特性有:
只执行一次:因为它是在类加载时执行的,所以整个类生命周期中只会执行一次。
优先级最高:静态初始化块是类第一次加载时最先执行的,甚至在main方法之前。
共享性强:由于它只执行一次,所以适合用来初始化类级别的资源,比如静态变量。
我们来看一个简单的例子:
运行这段代码,你会看到输出结果为:
看到没?静态初始化块在main方法之前执行!这是因为Java在执行代码前,必须先加载类,而静态初始化块在类加载时就会执行,这也就是为什么它的优先级最高。
2. 静态初始化块的实际应用场景
静态初始化块通常用于初始化一些需要在类加载时完成的逻辑,比如:
静态变量的初始化:在块中对静态变量进行一些复杂的计算或逻辑操作。
初始化共享资源:比如数据库连接池、文件资源等,这些资源只需要创建一次即可共享。
例如,假设我们有一个数据库连接池:
在这个例子中,数据库连接只需要创建一次,这样可以确保每次调用getConnection时都能拿到已经初始化好的连接。
非静态初始化块:每次创建对象时执行
接下来我们说说非静态初始化块。它没有static关键字,每次创建对象时都会被调用。非静态初始化块的执行顺序是在构造方法之前,但在静态初始化块之后。
1. 非静态初始化块是什么?
非静态初始化块和静态初始化块的区别在于:
每次创建对象时都会执行:只要你new一个对象,非静态初始化块就会执行一次。
优先级低于静态初始化块:静态块会最先执行,接着才是非静态块。
来看下面的例子:
输出结果为:
这里可以看到执行顺序是:
静态初始化块
main方法开始
非静态初始化块
构造方法
main方法结束
2. 非静态初始化块的实际应用场景
非静态初始化块通常用来初始化实例变量,或者是对对象进行一些准备操作。比如:
运行这段代码会输出:
每创建一个User对象,非静态初始化块都会执行一次,用于初始化默认的age属性,这样每个对象的age值都默认是18。
总结一下执行顺序
到这里,我们对静态初始化块和非静态初始化块的执行顺序已经有了清晰的了解,最终的执行顺序如下:
静态初始化块:在类加载时执行,只执行一次。
非静态初始化块:在对象创建时执行,每次创建对象都会执行。
构造方法:紧随非静态初始化块之后,构造方法会执行。
我们可以用这张图来帮助记忆:
什么时候用静态初始化块和非静态初始化块?
静态初始化块
适用于需要类级别的初始化逻辑,比如初始化静态变量、共享资源。
执行一次的操作,可以放在静态初始化块中,确保不会重复执行。
非静态初始化块
适用于对象级别的初始化逻辑,比如初始化实例变量。
每次创建对象都要执行的操作,可以放在非静态初始化块中。
END
好了!今天的初始化块总结到这里啦!希望大家可以通过这篇文章,彻底搞懂静态初始化块和非静态初始化块的区别以及实际应用。如果大家在面试时遇到类似问题,不妨用今天学到的知识点去回答,相信会给面试官留下深刻的印象!