容易出错的static代码块的执行顺序

java程序初始化的执行顺序:按照静态域的顺序来执行。父类静态变量—>父类静态代码块—>子类静态变量—>子类静态代码块—>父类非静态变量—>父类非静态代码块(是代码块,而不是方法)—>父类构造方法—>子类非静态变量—>子类非静态代码块—>子类构造方法

1、构造块优先于构造方法执行,每产生一个新的对象就调用一次构造块

class Person{
    {
        System.out.println("1.Person类的构造块");
    }
    public Person(){
        System.out.println("2.Person类的构造方法");
    }
}
public class Test2 {
    public static void main(String[] args) {
        new Person();
        new Person();
    }
}
1.Person类的构造块
2.Person类的构造方法
1.Person类的构造块
2.Person类的构造方法

2、静态构造块
(1)静态块优先于构造块执行。
(2)无论产生多少实例化对象,静态块都只执行一次

  • 非主类的静态块
    例一:
class Person{
    {
        System.out.println("1.Person类的构造块");
    }
    public Person(){
        System.out.println("2.Person类的构造方法");
    }
    static {
        //定义在非主类的静态块
        System.out.println("3.Person类的静态块");
    }
}
public class Test2 {
    public static void main(String[] args) {
        System.out.println("--start--");
        new Person();
        new Person();
        System.out.println("--end--");
    }
}
--start--
3.Person类的静态块
1.Person类的构造块
2.Person类的构造方法
1.Person类的构造块
2.Person类的构造方法
--end--

例二:

public class T{ 
       public static void main(String[] args) {
         System.out.println("---start---");
          new HelloB();
          new HelloA();
         System.out.println("---end---");
      }
   }
class HelloA {
    //构造方法
     public HelloA(){
         System.out.println("Hello A!父类构造方法");
     }
    //非静态代码块
    {
     System.out.println("i'm A class.父类非静态代码块");
    }
         //静态代码块
    static{
         System.out.println("static A 父类静态代码块");
        }
     }
class HelloB extends HelloA {
     //构造方法
      public HelloB(){
        System.out.println("Hello B! 构造方法");
     }
     //非静态代码块
     {
      System.out.println("i'm B class.非静态代码块");
     }
     //静态代码块
     static{
      System.out.println("static B 静态代码块");
        }
  }     
---start---
static A 父类静态代码块
static B 静态代码块
i'm A class.父类非静态代码块
Hello A!父类构造方法
i'm B class.非静态代码块
Hello B! 构造方法
i'm A class.父类非静态代码块
Hello A!父类构造方法
---end---
  • 在主类中的静态块
    (1)在主类中定义的静态块,优先于主方法(main)执行
class HelloA {
    //构造方法
     public HelloA(){
         System.out.println("Hello A!父类构造方法");
     }
    //非静态代码块
    { 
    System.out.println("i'm A class.父类非静态代码块");
    }
     //静态代码块
    static{
               System.out.println("static A 父类静态代码块");
        }
     }
 class HelloB extends HelloA {
     //构造方法
     public HelloB(){
        System.out.println("Hello B! 构造方法");
     }
//非静态代码块
     {
         System.out.println("i'm B class.非静态代码块");
     }
     //静态代码块
     static{
         System.out.println("static B 静态代码块");
        }
     public static void main(String[] args) {
         System.out.println("---start---");
          new HelloB();
          new HelloA();
         System.out.println("---end---");
    }
 }
static A 父类静态代码块
static B 静态代码块
---start---
i'm A class.父类非静态代码块
Hello A!父类构造方法
i'm B class.非静态代码块
Hello B! 构造方法
i'm A class.父类非静态代码块
Hello A!父类构造方法
---end---

例题解析:存在静态变量时的情况

public class Test4 {
    public static Test4 main1 = new Test4();
    public static Test4 main2 = new Test4();
    {
        System.out.println("构造块");
    }
    public Test4() {
        System.out.println("构造方法");
    }
    static {
        System.out.println("静态块");
    }
    public static void main(String[] args) {
        Test4 main3 = new Test4();
    }
}
构造块
构造方法
构造块
构造方法
静态块
构造块
构造方法

解析:在执行main之前先加载类,执行主类中的程序,加载类时并不会调用构造块和构造方法,只有静态域会执行,静态域中包含静态变量、静态块和静态方法,当执行到静态域时,按照静态域的顺序加载,并且静态块只在类的第一次加载时执行。执行静态域的第一个静态变量,输出构造块、构造方法,在执行第二个静态变量输出构造块、构造方法,最后执行静态块 ;静态块都已经初始化,所以main中不需要再执行静态块,直接执行构造块、构造方法。有些人会问为什么静态块不先执行呢?静态域是按照出现的顺序来执行的,一个执行完执行下一个。若静态块放在两个静态变量中间的时候,执行顺序为:构造块 构造方法 静态块 构造块 构造方法 构造块 构造方法

Java中主要有以下3种代码块: 1. 普通代码块 普通代码块也称为局部代码块,它是指定义在方法或语句中的代码块。普通代码块在执行到它们所在的语句时被执行,执行完后就被释放。 示例代码: ``` public class Test { public static void main(String[] args) { int a = 10; { int b = 20; System.out.println(a); // 输出10 System.out.println(b); // 输出20 } // System.out.println(b); // 编译错误,b已经超出了作用域 } } ``` 2. 静态代码块 静态代码块也称为类初始化块,它是指使用static修饰的代码块静态代码块在类加载时被执行,只执行一次,并且在构造函数执行前执行。 示例代码: ``` class MyClass { static { System.out.println("MyClass is loaded."); } } public class Test { public static void main(String[] args) { MyClass obj = new MyClass(); // 输出"MyClass is loaded." } } ``` 3. 构造代码块 构造代码块也称为实例初始化块,它是指定义在类中,没有用static修饰的代码块。构造代码块在每次创建对象时被执行,构造函数执行前执行。 示例代码: ``` class MyClass { { System.out.println("MyClass is created."); } public MyClass() { System.out.println("MyClass is initialized."); } } public class Test { public static void main(String[] args) { MyClass obj1 = new MyClass(); // 输出"MyClass is created."和"MyClass is initialized." MyClass obj2 = new MyClass(); // 输出"MyClass is created."和"MyClass is initialized." } } ``` 总结:Java中代码块可以分为普通代码块静态代码块和构造代码块。普通代码块定义在方法或语句中,静态代码块使用static修饰,构造代码块定义在类中,没有用static修饰。它们的执行顺序是:静态代码块 > 构造代码块 > 构造函数 > 普通代码块
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值