最近找工作,经常遇到笔试题上关于类初始化的题目,涉及到静态代码块,非静态代码块以及构造函数的加载顺序问题。今天复习了以前的笔记,来整理一下。
先给结论:
(1)对于单个类,没有new对象时,执行顺序为先执行静态代码块/初始化静态变量(按照顺序)。
(2)对于单个类,有new对象时,执行顺序为先执行静态代码块/初始化静态变量(按照顺序),然后非静态代码块/ 非静态变量(常量),最后构造函数。
(3)对于static修饰的代码块或者变量,只初始化一次。第二次new对象不会再执行。
(a)对于有继承关系的类,没有new对象时,执行顺序为先执行父类静态代码块/初始化静态变量(按照顺序),再执行子类静态代码块/初始化静态变量(按照顺序)。
(b)对于有继承关系的类,有new对象时,执行顺序为先执行父类静态代码块、子类静态代码块,然后父类非静态代码块/ 非静态变量(常量)和构造函数、子类非静态代码块和构造函数。
(c)对于有继承关系的类,对于static修饰的代码块或者变量,只初始化一次。第二次new对象不会再执行。
<static只能出现在在类中,不能在方法里面。>
结论(1)试验:
public class ExcuteOrderTest {
public ExcuteOrderTest(){
System.out.println("构造函数!");
}
{
_i ++;
System.out.println("非静态代码块::"+_i);
}
public static int _i = 10;
static {
_i = _i +2;
System.out.println("静态代码块::"+_i);
}
public static void main(String[] args) {
// ExcuteOrderTest test = new ExcuteOrderTest();
// System.out.println(_i);
// ExcuteOrderTest test1 = new ExcuteOrderTest();
// System.out.println(_i);
}
}
/**
输出:
静态代码块::12
分析:
可以看出没有new对象时,先执行的静态代码块,而且没有执行非静态代码块和构造函数。
**/
结论(2)试验:
public class ExcuteOrderTest {
public ExcuteOrderTest(){
System.out.println("构造函数!");
}
{
_i ++;
System.out.println("非静态代码块::"+_i);
}
public static int _i = 10;
static {
_i = _i +2;
System.out.println("静态代码块::"+_i);
}
public static void main(String[] args) {
ExcuteOrderTest test = new ExcuteOrderTest(); //
// System.out.println(_i);
// ExcuteOrderTest test1 = new ExcuteOrderTest();
// System.out.println(_i);
}
}
/**
输出:
静态代码块::12
非静态代码块::13
构造函数!
分析:
当new一个对象时,即使构造函数、非静态代码块(构造块)、静态代码块编写顺序打乱,执行顺序还是先静态代码块、非静态代码块、构造函数。对照试验就不贴上来了。
**/
** 结论(3)试验:**
public class ExcuteOrderTest {
public ExcuteOrderTest(){
System.out.println("构造函数!");
}
{
_i ++;
System.out.println("非静态代码块::"+_i);
}
public static int _i = 10;
static {
_i = _i +2;
System.out.println("静态代码块::"+_i);
}
public static void main(String[] args) {
ExcuteOrderTest test = new ExcuteOrderTest();
System.out.println(_i);
ExcuteOrderTest test1 = new ExcuteOrderTest();
System.out.println(_i);
}
}
/**
输出:
静态代码块::12
非静态代码块::13
构造函数!
13
非静态代码块::14
构造函数!
14
分析:
可以看到,在第二次new对象test1时,是没有重新执行静态变量初始化,以及静态代码块中的++操作的。
**/
下面试验的父类
public class ExcuteOrderTestParent {
public ExcuteOrderTestParent(){
System.out.println("ExcuteOrderTestParent构造函数!");
}
{
_i ++;
System.out.println("ExcuteOrderTestParent非静态代码块::::"+_i);
}
public static int _i = 20;
static {
_i = _i +2;
System.out.println("ExcuteOrderTestParent::静态代码块::"+_i);
}
}
结论(a)试验:
public class ExcuteOrderTest extends ExcuteOrderTestParent {
public ExcuteOrderTest(){
System.out.println("ExcuteOrderTest构造函数!");
}
{
_i ++;
System.out.println("ExcuteOrderTest非静态代码块::"+_i);
}
public static int _i = 10;
static {
_i = _i +2;
System.out.println("ExcuteOrderTest静态代码块::"+_i);
}
public static void main(String[] args) {
// ExcuteOrderTest test = new ExcuteOrderTest();
// ExcuteOrderTest test1 = new ExcuteOrderTest();
}
}
/**
输出:
ExcuteOrderTestParent::静态代码块::22
ExcuteOrderTest静态代码块::12
分析:
在没有new对象的时候,会只执行静态代码块,而且是先父类后子类。非静态代码块和构造方法不执行。
**/
结论(b)试验:
public class ExcuteOrderTest extends ExcuteOrderTestParent {
public ExcuteOrderTest(){
System.out.println("ExcuteOrderTest构造函数!");
}
{
_i ++;
System.out.println("ExcuteOrderTest非静态代码块::"+_i);
}
public static int _i = 10;
static {
_i = _i +2;
System.out.println("ExcuteOrderTest静态代码块::"+_i);
}
public static void main(String[] args) {
ExcuteOrderTest test = new ExcuteOrderTest();
// ExcuteOrderTest test1 = new ExcuteOrderTest();
}
}
/**
输出:
ExcuteOrderTestParent::静态代码块::22
ExcuteOrderTest静态代码块::12
ExcuteOrderTestParent非静态代码块::::23
ExcuteOrderTestParent构造函数!
ExcuteOrderTest非静态代码块::13
ExcuteOrderTest构造函数!
**/
结论(c)试验:
public class ExcuteOrderTest extends ExcuteOrderTestParent {
public ExcuteOrderTest(){
System.out.println("ExcuteOrderTest构造函数!");
}
{
_i ++;
System.out.println("ExcuteOrderTest非静态代码块::"+_i);
}
public static int _i = 10;
static {
_i = _i +2;
System.out.println("ExcuteOrderTest静态代码块::"+_i);
}
public static void main(String[] args) {
ExcuteOrderTest test = new ExcuteOrderTest();
ExcuteOrderTest test1 = new ExcuteOrderTest();
}
}
/**
输出:
ExcuteOrderTestParent::静态代码块::22
ExcuteOrderTest静态代码块::12
ExcuteOrderTestParent非静态代码块::::23
ExcuteOrderTestParent构造函数!
ExcuteOrderTest非静态代码块::13
ExcuteOrderTest构造函数!
ExcuteOrderTestParent非静态代码块::::24
ExcuteOrderTestParent构造函数!
ExcuteOrderTest非静态代码块::14
ExcuteOrderTest构造函数!
**/
参考文献(很透彻):https://www.jianshu.com/p/55c86e6c5c60