<clinit>与<init>方法

这两个方法是由java编译器自动生成,当java类中存在用static修饰的静态类型字段,或者存在使用static{}快包裹的逻辑时,编译器会自动生成方法。而当java类定义了构造函数或者其非static类成员变量被赋予初始值时,编译器会自动生成方法

init方法详解

public class ClinitTest extends MyClass{
    private Integer a = 3 ;
    public ClinitTest() {
       short b=8;
    }
    public ClinitTest(int c) {
        c=20;
    }
    {
        int d=33;
    }
}
class MyClass{
    protected int e=33;
    public MyClass(){
        int f=44;
    }
    public MyClass(int e){
        e=55;
    }
}

  1. 无论一个java类有无定义构造函数,编译器都会自动生成一个默认的构造函数init()
  2. init()主要完成java类的成员变量的初始化逻辑,同时执行被{}所包裹的快逻辑。如果java类中的成员变量没有被赋初值,则在init方法不会对其进行初始化
  3. 如果为java类显示定义了多个构造函数,无论是否是默认的无参构造函数,java编译器都会将java类成员变量的初始化逻辑嵌入到每一个构造函数中,并且嵌入的位置是在自生逻辑之前。
  4. 当java类显示继承了父类,则Java编译器会让子类的各个构造函数调用父类的默认构造函数init().,从而在子类实例化时完成父类成员变量的初始化逻辑
  5. 当父类中定义了多个构造函数时,子类构造函数会调用父类默认构造函数
  6. 子类构造函数对父默认构造函数的调用顺序,位于子类各个构造函数自生逻辑之前
Constant pool:
   #1 = Methodref          #5.#27         //  com/picc/java/MyClass."<init>":()V
   #2 = Methodref          #28.#29        //  java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   #3 = Fieldref           #4.#30         //  com/picc/java/ClinitTest.a:Ljava/lang/Integer;
   #4 = Class              #31            //  com/picc/java/ClinitTest
   #5 = Class              #32            //  com/picc/java/MyClass
   #6 = Utf8               a
   #7 = Utf8               Ljava/lang/Integer;
   #8 = Utf8               <init>
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               LocalVariableTable
  #13 = Utf8               d
  #14 = Utf8               I
  #15 = Utf8               this
  #16 = Utf8               Lcom/picc/java/ClinitTest;
  #17 = Utf8               b
  #18 = Utf8               S
  #19 = Utf8               (I)V
  #20 = Utf8               c
  #21 = Utf8               main
  #22 = Utf8               ([Ljava/lang/String;)V
  #23 = Utf8               args
  #24 = Utf8               [Ljava/lang/String;
  #25 = Utf8               SourceFile
  #26 = Utf8               ClinitTest.java
  #27 = NameAndType        #8:#9          //  "<init>":()V
  #28 = Class              #33            //  java/lang/Integer
  #29 = NameAndType        #34:#35        //  valueOf:(I)Ljava/lang/Integer;
  #30 = NameAndType        #6:#7          //  a:Ljava/lang/Integer;
  #31 = Utf8               com/picc/java/ClinitTest
  #32 = Utf8               com/picc/java/MyClass
  #33 = Utf8               java/lang/Integer
  #34 = Utf8               valueOf
  #35 = Utf8               (I)Ljava/lang/Integer;
{
  public com.picc.java.ClinitTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method com/picc/java/MyClass."<init>":()V
         4: aload_0
         5: iconst_3
         6: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         9: putfield      #3                  // Field a:Ljava/lang/Integer;
        12: bipush        33
        14: istore_1
        15: bipush        8
        17: istore_1
        18: return
      LineNumberTable:
        line 6: 0
        line 5: 4
        line 13: 12
        line 7: 15
        line 8: 18
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           15       0     1     d   I
            0      19     0  this   Lcom/picc/java/ClinitTest;
           18       1     1     b   S

  public com.picc.java.ClinitTest(int);
    descriptor: (I)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=2
         0: aload_0
         1: invokespecial #1                  // Method com/picc/java/MyClass."<init>":()V
         4: aload_0
         5: iconst_3
         6: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         9: putfield      #3                  // Field a:Ljava/lang/Integer;
        12: bipush        33
        14: istore_2
        15: bipush        20
        17: istore_1
        18: return
      LineNumberTable:
        line 9: 0
        line 5: 4
        line 13: 12
        line 10: 15
        line 11: 18
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           15       0     2     d   I
            0      19     0  this   Lcom/picc/java/ClinitTest;
            0      19     1     c   I

}

clinit方法详解

public class ClinitTest extends MyClass{
    private static int bb = 55;
    static {
        int uu=23;
    }
    public static void main(String[] args) {

    }
}
class MyClass{
    protected static int  ee = 26;
    static {
        int ff=90;
    }
}

可以看到static方法只完成了成员变量bb和局部变量uu的初始化,由此可见clinit不具备继承性,因为clinit只在类加载过程中被调用,而父类和子类是分别加载的,当父类加载完成之后,static成员变量初始化和static代码快中的逻辑已经执行完成,没必要在子类在执行一次

Constant pool:
   #1 = Methodref          #4.#22         //  com/picc/java/MyClass."<init>":()V
   #2 = Fieldref           #3.#23         //  com/picc/java/ClinitTest.bb:I
   #3 = Class              #24            //  com/picc/java/ClinitTest
   #4 = Class              #25            //  com/picc/java/MyClass
   #5 = Utf8               bb
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/picc/java/ClinitTest;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               args
  #17 = Utf8               [Ljava/lang/String;
  #18 = Utf8               <clinit>
  #19 = Utf8               uu
  #20 = Utf8               SourceFile
  #21 = Utf8               ClinitTest.java
  #22 = NameAndType        #7:#8          //  "<init>":()V
  #23 = NameAndType        #5:#6          //  bb:I
  #24 = Utf8               com/picc/java/ClinitTest
  #25 = Utf8               com/picc/java/MyClass
{
  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=1, args_size=0
         0: bipush        55
         2: putstatic     #2                  // Field bb:I
         5: bipush        23
         7: istore_0
         8: return
      LineNumberTable:
        line 5: 0
        line 7: 5
        line 8: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            8       0     0    uu   I
}

clinit和init的执行顺序
clinit是在类第一次被jvm加载时调用,而init是在实例化时调用。类的加载一定是在实例化之前,init每次实例化都会被调用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值