类的<cinit>()V方法、<init>()V、与方法调用

目录

()V方法

()V

 方法调用


<cinit>()V方法

一个类在加载的时候,编译器会按从上至下的顺序,收集所有 static 静态代码块静态成员赋值的代码,合并为一个特殊的方法 <cinit>()V :并调用。

 对应字节码

<init>()V

编译器会按从上至下的顺序,收集所有 {} 代码块和成员变量赋值的代码,形成新的构造方法,但原始构 造方法内的代码总是在最后
    private String a = "s1";

    {
        b = 20;
    }

    private int b = 10;

    {
        a = "s2";
    }

    {
    }

    public Demo3_8_2(String a, int b) {
        this.a = a;
        this.b = b;
    }

    public static void main(String[] args) {
        Demo3_8_2 d = new Demo3_8_2("s3", 30);
        System.out.println(d.a);
        System.out.println(d.b);
    }

对应字节码

扫描二维码关注公众号,回复: 13464591 查看本文章

 方法调用

对应字节码

  • new 是创建【对象】,给对象分配堆内存,执行成功会将【对象引用】压入操作数栈
  • dup 是复制操作数栈栈顶的内容,本例即为【对象引用】,为什么需要两份引用呢,一个是要配 invokespecial 调用该对象的构造方法 "<init>":()V (会消耗掉栈顶一个引用),另一个要 配合 astore_1 赋值给局部变量
  • 最终方法(fifinal),私有方法(private),构造方法都是由 invokespecial 指令来调用,属于静 态绑定 普通成员方法是由 invokevirtual 调用,属于动态绑定,即支持多态
  • 成员方法与静态方法调用的另一个区别是,执行方法前是否需要【对象引用】 比较有意思的是 d.test4(); 是通过【对象引用】调用一个静态方法,可以看到在调用 invokestatic 之前执行了 pop 指令,把【对象引用】从操作数栈弹掉了,所以通过对象引用调用一个静态方法会产生两条无用指令。
  • 还有一个执行 invokespecial 的情况是通过 super 调用父类方法

猜你喜欢

转载自blog.csdn.net/Promise_J_Z/article/details/121610188
今日推荐