static静态代码块与非静态代码块与构造函数执行顺序

本文详细解析了Java中构造函数、静态代码块、非静态代码块的执行顺序,通过具体示例帮助理解对象创建过程中的执行流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先执行块,后执行构造函数

块和声明变量的时候赋值,执行顺序是根据代码的顺序决定的

 

参考:Java中程序执行顺序(注意评论)

 

总结:静态代码块总是最先执行。

          非静态代码块跟非静态方法一样,跟对象有关。只不过非静态代码块在构造函数之前执行。

          父类非静态代码块、构造函数执行完毕后(相当于父类对象初始化完成), 才开始执行子类的非静态代码块和构造函数。

 

================================================================================

相同点:都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个,

    一般在代码块中对一些static变量进行赋值。

不同点:静态代码块在非静态代码块之前执行

(静态代码块—>非静态代码块—>构造方法)。

    静态代码块只在第一次new执行一次,之后不再执行,而非静态代码块在每new一次就执行一次。非静态代码块可在普通方法中定义(不过作用不大);而静态代码块不行。

 

JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。

 

Example1:

Java代码   收藏代码
  1. public class PuTong {  
  2.     public PuTong(){  
  3.         System.out.print("默认构造方法!-->");  
  4.     }  
  5.       
  6.     //非静态代码块  
  7.     {  
  8.         System.out.print("非静态代码块!-->");  
  9.     }  
  10.       
  11.     //静态代码块  
  12.     static{  
  13.         System.out.print("静态代码块!-->");  
  14.     }  
  15.       
  16.     public static void test(){  
  17.         {  
  18.             System.out.println("普通方法中的代码块!");  
  19.         }  
  20.     }  
  21. }  
  22.   
  23. //测试类  
  24. public class TestClass {  
  25.       
  26.     /** 
  27.      * 区别两次new静态与非静态代码块执行情况 
  28.      */  
  29.     public static void main(String[] args) {  
  30.         PuTong c1 = new PuTong();  
  31.         c1.test();  
  32.           
  33.         PuTong c2 = new PuTong();  
  34.         c2.test();  
  35.     }  
  36. }  
  37.   
  38. /* 
  39. 运行输出结果是: 
  40. 静态代码块!-->非静态代码块!-->默认构造方法!-->普通方法中的代码块! 
  41. 非静态代码块!-->默认构造方法!-->普通方法中的代码块! 
  42. */  

 

Example2:

 

Java代码   收藏代码
  1. package tags;  
  2.   
  3. public class Child extends Father{  
  4.       
  5.     static {  
  6.         System.out.println("child-->static");  
  7.     }  
  8.       
  9.     private int n = 20;  
  10.       
  11.     {  
  12.         System.out.println("Child Non-Static");  
  13.         n = 30;  
  14.     }  
  15.       
  16.     public int x = 200;  
  17.       
  18.     public Child() {  
  19.         this("The other constructor");  
  20.         System.out.println("child constructor body: " + n);  
  21.     }  
  22.       
  23.     public Child(String s) {  
  24.         System.out.println(s);  
  25.     }  
  26.       
  27.     public void age() {  
  28.         System.out.println("age=" + n);  
  29.     }  
  30.       
  31.     public void printX() {  
  32.         System.out.println("x=" + x);  
  33.     }  
  34.       
  35.     public static void main(String[] args) {  
  36.         new Child().printX();  
  37.     }  
  38. }  
  39.   
  40. class Father {  
  41.       
  42.     static {  
  43.         //System.out.println("n+"+n);  
  44.             //当n定义在下面时,会提示Cannot reference a field before it is defined,  
  45.             //所以必须把n定义移到上面才可以输出  
  46.         System.out.println("super-->static");  
  47.     }  
  48.       
  49.     public static int n = 10;  
  50.     public int x = 100;  
  51.       
  52.     public Father() {  
  53.         System.out.println("super's x=" + x);  
  54.         age();  
  55.     }  
  56.       
  57.     {  
  58.         System.out.println("Father Non-Static");  
  59.     }  
  60.       
  61.     public void age(){  
  62.         System.out.println("nothing");  
  63.     }  
  64. }  

实例参考:http://yanxuxin.iteye.com/blog/578060

 

有两个要点:

1、父类、子类非静态代码块何时初始化?

2、父类调用重写方法时,到底执行的是哪个方法?

 

 

 结果:

 

super-->static

child-->static

Father Non-Static

super's x=100

age=0

Child Non-Static

The other constructor

child constructor body: 30

x=200

 

 

父类静态代码块 -> 子类静态代码块

-> 父类非静态代码块 -> 父类构造函数

-> 子类非静态代码块 -> 子类构造函数

 

 

 

java中,在使用new操作符创建一个类的实例对象的时候,开始分配空间并将成员变量初始化为默认的数值,注意这里并不是指将变量初始化为在变量定义处的初始值,而是给整形赋值0,给字符串赋值null 这一点于C++不同,(student.name = null , student.age = 0 )

 

然后在进入类的构造函数。

在构造函数里面,首先要检查是否有this或者super调用,this调用是完成本类本身的构造函数之间的调用,super调用是完成对父类的调用。二者只能出现一个,并且只能作为构造函数的第一句出现。在调用this和super的时候实现程序的跳转,转而执行被调用的this构造函数或者super构造函数。

在this和super执行完毕,程序转而执行在类定义的时候进行的变量初始化工作。

这个执行完毕,才是构造函数中剩下的代码的执行。

转载:http://uule.iteye.com/blog/1558891

 

<think>嗯,用户想了解Java静态代码块执行顺序初始化过程。好的,首先我得回忆一下相关知识。记得静态代码块在类加载的时候执行,而且只执行一次。对吧?那静态代码块之间的顺序是按照它们在代码中的书写顺序执行的。比如如果有两个静态代码块,先写的那个会先执行。 然后,静态代码块会在main函数之前执行,对吧?因为main函数是程序的入口,但类加载的过程其实在main执行之前就完成了。所以静态代码块会在类加载的时候执行,然后才执行main方法。例如用户给的示例代码里,静态代码块12会在main函数输出之前打印。 另外,用户提供的引用资料里提到,静态代码块优先于各种代码块构造函数,包括实例初始化块构造方法。所以当一个类被实例化的时候,静态代码块已经执行过了,实例初始化块构造方法会在之后执行。如果有父类的话,还需要考虑父类的静态代码块执行,然后是子类的静态代码块,接着是父类的实例初始化块构造方法,最后是子类的实例初始化块构造方法。这点需要确认是否正确。 还要注意静态代码块只能访问静态成员,不能访问实例变量或方法。比如在静态代码块里调用非静态的方法或变量会导致编译错误。比如引用3中的示例,静态代码块中尝试访问非静态的x变量就会出错,所以必须只能调用静态的y变量getY方法。 现在需要把这些整理成一个清晰的步骤,可能还需要示例代码来说明执行顺序。用户可能需要知道静态代码块在类加载时的具体时机,以及它们如何影响程序的初始化过程。另外,相关问题部分需要生成几个相关的问题,比如其他初始化块的执行顺序比较,或者如何利用静态代码块进行资源初始化等。 还要确保回答中使用正确的中文,避免术语错误。同时,按照用户的要求,行内数学表达式用$...$,不过这个问题可能不涉及数学公式,但如果有的话需要注意格式。独立公式用$$...$$,但同样可能不适用。LaTeX语法正确,但这里主要是代码块文字描述。 总结一下,回答的结构应该包括:静态代码块的定义,执行顺序的规则(多个静态代码块顺序,父类子类的顺序main函数的关系),在初始化中的作用,示例代码,以及可能的相关问题。需要引用提供的参考资料来支持回答,比如引用1引用2中的内容,说明静态代码块在main之前执行,以及多个静态代码块顺序。 可能还需要检查是否遗漏了其他重要点,比如静态代码块在类第一次被主动使用时触发,比如创建实例、访问静态方法或变量等。这时候类才会被加载,静态代码块才会执行。例如,如果只是声明一个类的引用而没有实际使用,静态代码块不会执行。这点是否需要在回答中提到呢?用户的问题是关于执行顺序初始化过程,所以可能有必要提到类加载的触发条件。 总之,回答需要覆盖以下几点: 1. 静态代码块的定义作用。 2. 执行顺序的规则(多个静态块、继承中的顺序)。 3. main函数其他初始化块的执行顺序。 4. 示例代码及解释。 5. 静态代码块的使用场景注意事项。 6. 引用中的相关内容支持这些点。 然后生成相关问题,比如实例初始化块的比较,继承中的执行顺序,或者实际应用中的使用场景。</think>### Java静态代码块执行顺序初始化过程解析 #### 一、静态代码块的核心特性 1. **执行时机** 静态代码块在**类加载阶段**执行,且**仅执行一次**,优先于实例初始化块、构造方法`main`函数[^2]。 例如,在类首次被主动使用时(如创建实例、调用静态方法或访问静态字段),JVM会触发类加载。 2. **执行顺序规则** - **同一类中**:多个静态代码块按**代码书写顺序**依次执行。 - **继承关系中**:父类静态代码块 → 子类静态代码块 → 父类实例初始化块/构造方法 → 子类实例初始化块/构造方法[^2]。 --- #### 二、执行顺序示例 ```java class Parent { static { System.out.println("父类静态代码块"); } { System.out.println("父类实例初始化块"); } Parent() { System.out.println("父类构造方法"); } } class Child extends Parent { static { System.out.println("子类静态代码块1"); } static { System.out.println("子类静态代码块2"); } { System.out.println("子类实例初始化块"); } Child() { System.out.println("子类构造方法"); } public static void main(String[] args) { System.out.println("Main函数开始"); new Child(); System.out.println("Main函数结束"); } } ``` **输出结果**: ``` 父类静态代码块 子类静态代码块1 子类静态代码块2 Main函数开始 父类实例初始化块 父类构造方法 子类实例初始化块 子类构造方法 Main函数结束 ``` **关键过程**: 1. 类加载阶段执行父类子类的静态代码块。 2. `main`函数作为入口,在静态代码块执行。 3. 对象实例化时,按继承链顺序执行实例初始化块构造方法。 --- #### 三、静态代码块的作用 1. **初始化静态资源** 常用于加载配置文件、初始化静态变量等一次性操作。 例如: ```java class DatabaseConfig { static String URL; static { URL = "jdbc:mysql://localhost:3306/mydb"; System.out.println("数据库配置已加载"); } } ``` 2. **强制类加载** 通过静态代码块确保类在使用前完成初始化[^3]。 --- #### 四、注意事项 1. **静态代码块只能访问静态成员**,尝试访问实例变量或方法会导致编译错误[^3]。 2. 若类未被主动使用,静态代码块不会执行。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值