在对象的方法中使用对象的成员变量时,为什么喜欢先把它赋值给这个方法的局部变量?为了不可变性吗?

灰机不会飞
  • 21

先上代码:

public class SomeObject{
    private Subscription subscription;
    public void foo(long n){
        Subscription s = this.subscription;
        s.request(n);
    }
}

反正自己平时写代码时,在foo(n)中就直接掉用this.subscription.request(n)了。但其实仔细想想,好像很多比较规范的源码中都会先把成员变量赋值给一个方法的局部变量,再操作这个局部变量。
我个人的第一感觉是:是不是防止在代码中出现类似下面的代码,进而造成改变了成员变量的实时。即:从类的不变性角度触发才像上面这样写:

public void foo(long n){
    //写代码、或修改代码时,在这个方法中需要换一个subscription对象
    if(
        this.subscription.request(n)
            .notSatisfySomeCondition()
    ){
        this.subscription = new AnotherSubscriptionImpl();
        this.subscription.request(n);
    }
}

个人感觉自己这样理解没问题,有谁能给个准话吗?
类似的代码还有很多,我挑几个立即就能想到的:

//reactor-core的BaseSubscriber.java
    @Override
    public final void request(long n) {
        if (Operators.validate(n)) {
            Subscription s = this.subscription;
            if (s != null) {
                s.request(n);
            }
        }
    }

//HashMap的随便一个方法,如putVal(...)
 final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        //这里的tab = this.table   源码是tab=table,这里为了突出效果而加了this.
        if ((tab = this.table) == null || (n = tab.length) == 0)
        //...process with tab but not table
 }

补充:这里不是要讨论不可变类的实现,因为它的内容比较多。

回复
阅读 677
2 个回答
✓ 已被采纳

image.png
你可以看下我上图的例子,对比一下左侧代码23行和25,以及右侧生成的字节码。你会发现获取b和c只需要调用iload,从本地方法栈取值,但是获取a的时候,aload->获取this,getfield->获取a的值,需要两步操作。

把成员变量赋值给局部变量是为了抠性能,对于底层还是有必要的
对于业务层就比较无所谓了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏