You can use == to compare equality of string references. It might be a good idea to explain the String Pool and limitation of using only ==, and then what the differences are between equals and compareTo. The main one being that equals will first do == to see if the string references are equivalent as this is extremely fast (compareTo probably does this to?), and if this fails, will then go on to do a lexical comparison, which is slow.Matt Oates
public class StringTest {public static String myString = "Hello World";public static class A {public final static String myString = "Hello World";}public static class B {public final static String myString = "Hello World";}public static void main(String[] args) {// Same class, same constant poolif (myString == "Hello World") {System.out.println("References in the same class match");}// Different classes, runtime string poolif (A.myString == B.myString) {System.out.println("References across classes match");}// Manipulated Strings <-> No string poolString v = "Hello ".concat("World");if (v != myString) {System.out.println(v);System.out.println(myString);System.out.println("--> See the difference - equals=" + v.equals(myString));}}}
References in the same class matchReferences across classes matchHello WorldHello World--> See the difference - equals=true
$ javap -c StringTestCompiled from "StringTest.java" public class StringTest extends java.lang.Object{ public static java.lang.String myString; static {}; Code:0: ldc #10; //String Hello World 2: putstatic #12; //Field myString:Ljava/lang/String; 5: return public de.rtjava.test.StringTest(); Code: 0: aload_0 1: invokespecial #17; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #12; //Field myString:Ljava/lang/String;3: ldc #10; //String Hello World 5: if_acmpne 16 8: getstatic #23; //Field java/lang/System.out:Ljava/io/PrintStream; 11: ldc #29; //String References in the same class match 13: invokevirtual #31; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 16: getstatic #23; //Field java/lang/System.out:Ljava/io/PrintStream; 19: ldc #37; //String References across classes match 21: invokevirtual #31; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 24: ldc #39; //String Hello 26: ldc #41; //String World 28: invokevirtual #43; //Method java/lang/String.concat:(Ljava/lang/String;)Ljava/lang/String; 31: astore_1 32: aload_1 33: getstatic #12; //Field myString:Ljava/lang/String; 36: if_acmpeq 63 39: getstatic #23; //Field java/lang/System.out:Ljava/io/PrintStream; 42: aload_1 43: invokevirtual #31; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 46: getstatic #23; //Field java/lang/System.out:Ljava/io/PrintStream; 49: getstatic #12; //Field myString:Ljava/lang/String; 52: invokevirtual #31; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 55: getstatic #23; //Field java/lang/System.out:Ljava/io/PrintStream; 58: ldc #49; //String --> See the difference 60: invokevirtual #31; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 63: return}
I believe this statement on the page is incorrect:
"Remember that no String objects are ever eligible for garbage collection. Once a String is created, it takes up memory until the JVM terminates."
Yes, Strings are immutable objects.
Yes, literal strings, and strings created at compile time via constant expressions, are interned, and interned Strings won't be garbage collected.
But... not all Strings are interned!
And why shouldn't a non-interned String be eligible for garbage collection? If there are no references to it, it should be able to be garbage collected... and if it's not interned, then it certainly can be the case that nothing else points to it anymore.
In short: I'm pretty sure the statement is incorrect.
I'd really like to see some sort of reference, from Sun's website, or the JLS, indicating why Strings are *never* garbage collected. Otherwise, the statement should be replaced with something more accurate.
The code example is still valid; it does create a large number of temporary String objects that get thrown away quickly, and that does create a performance issue, mitigated a bit by generational garbage collection (since the temporary Strings don't live very long). But I don't believe it counts as a memory leak.
For more information, see:
http://java.sun.com/developer/TechTips/1999/tt0114.html
http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html