关于静态代码块,构造方法,构造代码块的执行先后顺序

总结一下:

1.执行顺序:静态代码块>构造代码块>构造方法
理由:静态代码块(static{})在类加载的时候执行一次。
构造代码块({}内的部分)在每一次创建对象时执行,始终在构造方法前执行。
构造方法在新建对象时调用( 就是new的时候 )。
注意: a.静态代码块在类加载的时候就执行,所以它的优先级高于入口main()方法。
b.当三种形式不止一次出现,同优先级是按照先后顺序执行。

来看一道题巩固一下:

public class B
{
    
    
    public static B t1 = new B();
    public static B t2 = new B();
    {
    
    
        System.out.println("构造块");
    }
    static
    {
    
    
        System.out.println("静态块");
    }
    public static void main(String[] args)
    {
    
    
        B t = new B();
    }
}

所以这段代码的输出结果是?

构造块,构造块,静态块,构造块

解释:

1.程序入口main方法要执行首先要加载类B
2.静态域:分为静态变量,静态方法,静态块。这里面涉及到的是静态变量和静态块,当执行到静态域时,按照静态域的顺序加载。并且静态域只在类的第一次加载时执行
3.每次new对象时,会执行一次构造块和构造方法,构造块总是在构造方法前执行(当然,第一次new时,会先执行静态域,静态域〉构造块〉构造方法)
注意:加载类时并不会调用构造块和构造方法,只有静态域会执行
4.根据前三点,首先加载类B,执行静态域的第一个静态变量,static b1=new B,输出构造块和构造方法(空)。ps:这里为什么不加载静态方法呢?因为执行了静态变量的初始化,意味着已经加载了B的静态域的一部分,这时候不能再加载另一个静态域了,否则属于重复加载 了(静态域必须当成一个整体来看待。否则加载会错乱) 于是,依次static b2 =new B,输出构造块,再执行静态块,完成对整个静态域的加载,再执行main方法,new b
链接:https://www.nowcoder.com/questionTerminal/ab6eb06face84c4e81ab5bc6f0f7f258
来源:牛客网

开始时JVM加载B.class,对所有的静态成员进行声明,t1 t2被初始化为默认值,为null,又因为t1 t2需要被显式初始化,所以对t1进行显式初始化,初始化代码块→构造函数(没有就是调用默认的构造函数),咦!静态代码块咋不初始化?因为在开始时已经对static部分进行了初始化,虽然只对static变量进行了初始化,但在初始化t1时也不会再执行static块了,因为JVM认为这是第二次加载类B了,所以static会在t1初始化时被忽略掉,所以直接初始化非static部分,也就是构造块部分(输出’‘构造块’’)接着构造函数(无输出)。接着对t2进行初始化过程同t1相同(输出’构造块’),此时就对所有的static变量都完成了初始化,接着就执行static块部分(输出’静态块’),接着执行,main方法,同样也,new了对象,调用构造函数输出(‘构造块’)
总结:
1、每调用一次构造方法,则执行一次构造块
2、静态块只在类加载的时候加载一次
3、有多个静态变量或块时,按声明顺序加载
下面再看一道题:

public class HelloB extends HelloA {
    
    
	
	 public HelloB(){
    
    
		 System.out.println("B的构造方法");
	 }
	 {
    
    
	     System.out.println("B的构造代码块");
	 }
	 static{
    
    
	     System.out.println("B的静态代码块");
	 }
	 //public static HelloB hB = new HelloB();
	 public static void main(String[] args){
    
    
	     new HelloB();//调用B的构造方法
	 }
}

class HelloA{
    
    
	 public HelloA(){
    
    
		 System.out.println("A的构造方法");
	 }
	 {
    
    
	     System.out.println("A的构造代码块");
	 }
	 static{
    
    
	     System.out.println("A的静态代码块");
	 }
} 

输出的结果大家都应该是知道的:

A的静态代码块
B的静态代码块
A的构造代码块
A的构造方法
B的构造代码块
B的构造方法

猜你喜欢

转载自blog.csdn.net/qq_42678668/article/details/110389070
今日推荐