2

What is the purpose of copying value reference into val variable, as oppose to using it directly?

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;
}
user2418306
  • 2,352
  • 1
  • 22
  • 33
  • Unclear, but the member variable is still used via `value.length`. – Andy Turner May 25 '16 at 07:42
  • 1
    @AndyTurner, but that's the answer, right? If `value` changes during execution of `hashCode` you could get an `ArrayIndexOutOfBoundsException` or simply compute a faulty hash code. – aioobe May 25 '16 at 07:44
  • @aioobe how does `private final char[] value` change during execution, in a way that checking its length would detect? And do you really expect the elements of `val` to change either, what with `String` being immutable? – Andy Turner May 25 '16 at 07:46
  • Oh, didn't notice the comment in the code. Then it seems unnecessary. – aioobe May 25 '16 at 07:55
  • Questions about code style don't always have a good answer. I'm inclined to vote this for close as being opinion-based. You could re-phrase the question however to ask more generally "is there any reason to copy a value to a local variable" and then you might get some interesting answers. – davmac May 25 '16 at 09:23

2 Answers2

0

This is performance optimization according to Martin Buchholz

copying to locals produces the smallest bytecode

See also:
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     |
+----------------------+----------------------------+------------------------------+
Community
  • 1
  • 1
user2418306
  • 2,352
  • 1
  • 22
  • 33
  • This is true only if the value of the local is used more than once, which in this case, it is not. In fact, copying the value into the local uses more bytecode - 55 bytes versus 53, for this particular method, when I tried it myself. – davmac May 25 '16 at 09:21
  • Just to add @davmac for given question there is no copy of data happening its just reference is copying in another variable. – Sumit Singh May 25 '16 at 09:26
  • @SumitSingh the _value_ that I referred to being copied _is_ the reference. A reference is ultimately represented as a pointer and a pointer _is_ data. It is wrong to claim that "there is no copy of data". – davmac May 25 '16 at 09:27
  • Shouldn't the OP's question be marked as a dup of the referenced question? – Jim Garrison May 25 '16 at 19:09
-1

It could be for performance. According to this, accessing a local variable is (very slightly) faster than accessing an instance variable. In the Java base library, such micro-optimizations are of course a good thing.

Community
  • 1
  • 1
Thomas
  • 174,939
  • 50
  • 355
  • 478