12

In JDK 8, String.equals implements as

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

Why does the iteration uses two operations - incrementing i and decrementing n instead of something like that:

while (i < n) {
    if (v1[i] != v2[i])
        return false;
    i++;
}

or

while (i-- != 0) {
    if (v1[i] != v2[i])
        return false;
}

with one increment or decrement operation?

I suppose, it is somehow related to JVM bytecode optimization but don't understand how.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Artem Zyuzko
  • 131
  • 3

2 Answers2

5

I think this is dead code, left over from the days when Strings still shared backing arrays and had offset and count, so that you needed to tweak the indexes a little.

The String implementation was changed in JDK 7 Update 6 (many people were upset about that, especially that it happened in a minor release). Strings don't share backing array anymore (unless the Strings are themselves equal, in which case a new deduplicator tries to re-share them).

You can see a discussion of the old implementation over at "how does String.equals() work".

Community
  • 1
  • 1
Thilo
  • 257,207
  • 101
  • 511
  • 656
  • 1
    Another interesting aspect is that equals does not make use of the Strings' hashCode. This is discussed at http://stackoverflow.com/questions/14262431/why-does-the-equals-method-in-string-not-use-hash?lq=1 – Thilo Nov 06 '15 at 13:36
  • And now that the arrays are not shared anymore, one could also compare object identity for the two arrays (`if (value == anotherString.value) return true`). I suppose that doesn't happen much. – Thilo Nov 06 '15 at 13:41
  • Haven't they already done that when they compare identity of the Strings? – Paul Boddington Nov 06 '15 at 13:45
  • 1
    @PaulBoddington: No. `new String("a") != new String("a")` (but they could potentially have the same backing array, even in JDK8) – Thilo Nov 06 '15 at 13:49
  • Thanks. I didn't know that, I thought all strings had their own array now. – Paul Boddington Nov 06 '15 at 13:50
  • @PaulBoddington: check out the source for the `new String(string)` constructor. In the example above all three Strings (counting the literal as well) have the same backing array in JDK8. http://hg.openjdk.java.net/jdk8/jdk8/jdk/annotate/687fd7c7986d/src/share/classes/java/lang/String.java#l151 – Thilo Nov 06 '15 at 13:53
  • I'd just done it, before reading your comment. In retrospect it was a stupid comment of mine. – Paul Boddington Nov 06 '15 at 13:59
0

Actually this java code has no direct relation to real machine code (at least for modern desktop/server JVM). You can read about "Intrinsic Methods in HotSpot VM". E.g. When will JVM use intrinsics

Community
  • 1
  • 1
sibnick
  • 3,995
  • 20
  • 20