2016-05-25 25 views
2

复制value参考到val变量的目的是什么,反对直接使用它?为什么在String#hashCode中有一个局部变量引用值数组?

public int hashCode() { 
    int h = hash; 
    if (h == 0 && value.length > 0) { 
     char val[] = value; // private final char value[]; 

     for (int i = 0; i < value.length; i++) { 
      h = 31 * h + val[i]; 
     } 
     hash = h; 
    } 
    return h; 
} 
+0

不清楚,但成员变量仍然通过'value.length'使用。 –

+1

@AndyTurner,但这就是答案,对吧?如果在执行'hashCode'过程中'value'发生了变化,您可能会得到一个'ArrayIndexOutOfBoundsException'或者简单地计算一个错误的哈希码。 – aioobe

+0

@aioobe执行过程中'private final char [] value'是如何改变的,通过检查它的长度来检测?你真的期望'val'的元素可以改变,'String'是不可变的吗? –

回答

0

这是根据Martin Buchholz

复制到当地人的性能优化产生最小 字节码

参见:
In ArrayBlockingQueue, why copy final member field into local final variable?


+----------------------+----------------------------+------------------------------+ 
| h = 31 * h + val[i]; | h = 31 * h + value[i];  | hash = 31 * hash + value[i]; | 
+----------------------+----------------------------+------------------------------+ 
| LINENUMBER 1471 L7 | LINENUMBER 14 L6   | LINENUMBER 13 L4    | 
| BIPUSH 31   | BIPUSH 31     | ALOAD 0      | 
| ILOAD 1    | ILOAD 1     | BIPUSH 31     | 
| IMUL     | IMUL      | ALOAD 0      | 
| ALOAD 2    | ALOAD 0     | GETFIELD String.hash : I  | 
| ILOAD 3    | GETFIELD String.value : [C | IMUL       | 
| CALOAD    | ILOAD 2     | ALOAD 0      | 
| IADD     | CALOAD      | GETFIELD String.value : [C | 
| ISTORE 1    | IADD      | ILOAD 1      | 
|      | ISTORE 1     | CALOAD      | 
|      |       | IADD       | 
|      |       | PUTFIELD String.hash : I  | 
+----------------------+----------------------------+------------------------------+ 
+0

只有当本地的值不止一次被使用时,这才是真实的,在这种情况下,它不是。实际上,当我自己尝试时,将值复制到本地时使用更多的字节码 - 55字节与53字节,对于此特定方法。 – davmac

+0

仅仅为给定的问题添加@davmac就没有数据副本发生,只是它引用的是复制到另一个变量中。 –

+0

@SumitSingh我提到的_value_被复制_is_参考。引用最终表示为指针和指针_is_数据。声称“没有数据副本”是错误的。 – davmac

-1

它可能是为了表现。根据this,访问本地变量比访问实例变量(非常轻微)要快。在Java基础库中,这样的微观优化当然是一件好事。

相关问题