<init>与<clinit> 与 类的初始化顺序


这两种方法有什么区别呢?

首先:这两个方法一个是虚拟机在装载一个类初始化的时候调用的(clinit)。另一个是在类实例化时调用的(init)

 

首先说说类的初始化:

在Java代码中,一个正确的初始值是通过类变量初始化语句或者静态初始化语句给出的。一个类变量初始化语句是

变量声明后的等号和表达式:

Java代码   收藏代码
  1. class Example {  
  2.        static int size = 3 * (int) (Math.random() * 5.0);  
  3. }  

 

静态初始化语句是一个以static开头的语句块:

Java代码   收藏代码
  1. class Example{  
  2.      static int size;  
  3.      static {  
  4.            size = 3 * (int) (Math.random() * 5.0);  
  5.      }  
  6. }  

 所有的类变量初始化语句和类型的静态初始化语句都被Java编译器收集到了一起,放在一个特殊的方法中。这个方法就是<clinit>

 

我们在来看看<init>这个方法:

<init>方法是在一个类进行对象实例化时调用的。实例化一个类有四种途径:调用new操作符;调用Class或java.lang.reflect.Constructor对象的newInstance()方法;调用任何现有对象的clone()方法;通过java.io.ObjectInputStream类的getObject()方法反序列化。

 

Java编译器会为它的每一个类都至少生成一个实例初始化方法。在Class文件中,被称为"<init>"

 

现在知道了吧, 一个是用于初始化静态的类变量, 一个是初始化实例变量!




<init><clinit>

<init>

Java在编译之后会在字节码文件中生成<init>方法,称之为实例构造器,该实例构造器会将语句块,变量初始化,调用父类的构造器等操作收敛到<init>方法中,收敛顺序(这里只讨论非静态变量和语句块)为: 
1. 父类变量初始化 
2. 父类语句块 
3. 父类构造函数 
4. 子类变量初始化 
5. 子类语句块 
6. 子类构造函数

所谓收敛到<init>方法中的意思就是,将这些操作放入到<init>中去执行

<clinit> 
Java在编译之后会在字节码文件中生成<clinit>方法,称之为类构造器,类构造器同实例构造器一样,也会将静态语句块,静态变量初始化,收敛到<clinit>方法中,收敛顺序为: 
1. 父类静态变量初始化 
2. 父类静态语句块 
3. 子类静态变量初始化 
4. 子类静态语句块

<clinit>方法是在类加载过程中执行的,而<init>是在对象实例化执行的,所以<clinit>一定比<init>先执行。所以整个顺序就是: 
1. 父类静态变量初始化 
2. 父类静态语句块 
3. 子类静态变量初始化 
4. 子类静态语句块 
5. 父类变量初始化 
6. 父类语句块 
7. 父类构造函数 
8. 子类变量初始化 
9. 子类语句块 
10. 子类构造函数

初始化顺序

如下父类代码

public class Parent {
    static int a = 1;
    int b = 1;
    static {
        System.out.println("parent static block(a):" + (++a));
    }
    {
        System.out.println("parent  block(b):" + (++b));
    }
    public Parent() {
        System.out.println("parent construction");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

子类代码

public class Child extends Parent {
    static int a = 1;
    int b = 1;
    static {
        System.out.println("child static block(a):" + (++a));
    }
    {
        System.out.println("child  block(b):" + (++b));
    }
    public Child() {
        System.out.println("child construction");
    }
    public static void main(String[] args) {
        new Child();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

最终输出结果为

parent static block(a):2
child static block(a):2
parent  block(b):2
parent construction
child  block(b):2
child construction
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值