避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可,为什么呢?

2,594 阅读2分钟

一.问题

阿里规约里有这么一条编程规范:

避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可

这里不禁会想,如果通过对象引用了此类的静态变量或静态方法,会增加哪些成本

二.原因

网上找了一些博客,有些是说,因为new了对象,所以消耗了内存???EXM?看看以下demo:

public class Test {

    public static int a = 0;

    public void setA() {
        this.a = 1;
        // Test.a = 1;
    }

}

因为我想的是在一个对象里,通过this访问静态变量,也就不存在什么new不new的,所以先看看this.a和Test.a有啥区别

  • 解析一下字节码并对比一下:

图左是this.a代码,图右是Test.a代码,差异就在Code属性表里,Code属性表是用来存储方法代码的,左右对比可以看出,左边多aload_0和pop两条指令。aload_0指令是将第一个引用类型局部变量推送至栈顶,pop是将栈顶数值弹出,这里唯一的引用类型就是this了,所以线程应该是把this入栈,然后访问了this指向的对象。

  • java对象的内存布局

对象头:包括hashcode、GC分代年龄、锁状态标识、线程持有的锁、偏向线程ID、偏向时间戳等。还有一部分是类型指针,即对象指向它的类元数据的指针

实例数据:对象真正存储的有效信息

对齐填充:占位符作用

  • JVM内存布局-方法区

方法区与java堆一样,是各个线程共享的内存区域,它用于存储虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据

结合上述,可以得出 this.a 通过引用访问对象,通过对象访问类元信息,最后才访问到静态变量,是折腾了一番。