0

Today I ran into a silly bug. I had to compare 2 strings and I used '==' accidentally. (This can happen a lot when you frequently switch between languages where you can compare strings using the '==' operator).
I didn't pay enough attention because I thought the unit tests are going to detect problems like that. What I didn't know was that java tries to share strings to save memory.
So, non of the unit tests failed (because the strings were shared) and I continued writing code. The long and short of it: some time later I used this method with a dynamically created string (new String("other string")), which had another id (hash) than String s = 'other string'.

Is there any way to prevent Java from sharing strings during unit tests. I don't care about the memory usage (during unit tests) since it is more important for the code to work.
I don't want to use new String(...) every time a unit test uses a string.

Community
  • 1
  • 1
Matt3o12
  • 4,192
  • 6
  • 32
  • 47
  • First of all: you shouldn't rely on the hashcode to uniquely identify a string. Your problem is rather unclear though; why do you use `new String()` in the first place? Why can't you just use `.equals()`? – Jeroen Vannevel May 18 '14 at 13:34
  • 2
    Static code analysis tools will help you a lot for those scenarios – guido May 18 '14 at 13:35
  • @JeroenVannevel I used == accidentally but I wrote unit tests to prevent such problems. However I didn't know that java shares strings to save memory. My question is: can I prevent java from doing so that every string will have a unique value? – Matt3o12 May 18 '14 at 13:40
  • @guido can you give me more information about such code analysis tools? Where can I find them? – Matt3o12 May 18 '14 at 13:41
  • 1
    Here's an explanation of the mechanism involved: http://stackoverflow.com/a/3451183/931925 – minopret May 18 '14 at 13:41
  • Good free code analysis tools include PMD and FindBugs. For another purpose than the purpose here I also suggest Checkstyle. – minopret May 18 '14 at 13:42
  • 1
    @Matt3o12 sure, pmd.sourceforge.net , findbugs.sourceforge.net, www.sonarqube.com – guido May 18 '14 at 13:43
  • 1
    If the string literals are in the same class, they will be shared whatever happens. – Deduplicator May 18 '14 at 13:46
  • Note that Java doesn't share Strings "to save memory". (At least that's not the primary goal.) Rather, several internal functions of the JVM depend on being able to effectively do `==` on String literals. If you were to somehow inhibit default interning you'd break the JVM. – Hot Licks May 18 '14 at 13:49
  • 1
    (What Java *should* have done is not allow `==` between references, but require some other symbol (some languages use `===`) instead, so that using `==` would be a compile error. But that's water under the dam/over the bridge.) – Hot Licks May 18 '14 at 13:56

1 Answers1

1

The mechanism involved is "interning" as described here: https://stackoverflow.com/a/3451183/931925

In short, it is done by the Java Virtual Machine (JVM). We can imagine using a virtual machine that specifically for this purpose would depart from the Java specification. But then it would be necessary to test also on another JVM that does comply with the specification, in order to ensure that the code will "run anywhere".

Instead, good free static analysis tools for Java such as PMD and FindBugs are likely to be more helpful to detect this sort of bug before runtime. (For another purpose than the purpose here I also suggest Checkstyle.)

Community
  • 1
  • 1
minopret
  • 4,726
  • 21
  • 34