Question

I remember reading a section, possibly in Bloch's Effective Java, that said that for most cases, where

String a = "fish";
String b = "fish";

that a == b in most cases because Strings are immutable. But that due to temporary construction of objects or some such, new String("fish") would yield a distinct object reference.

I looked through Bloch chapters on equals(), immutability, and object creation, but cannot find this bit I remember!! Tearing my hair out, does anyone remember where is the description of why this is? It may not even be in EJ but I'd like to find it. Hint: where is this explained is my actual question.

Was it helpful?

Solution

It's not related to immutability. It's the way strings are handled by the JVM. A string literal with the same contents represents the same object ("string literal" means roughly "text surrounded by quotes"). There is a table of string objects in the JVM, and each string literal has exactly one object in that table.

However, when you expicitly create a new instance, you construct a new string object based on the string object taken from the table.

From any string formed by not using a literal (but by calling toString(), by instantiating, etc.) you can get the object from the jvm table by calling str.intern(). The intern() method returns exactly one instance for each character sequence that exists. new String("fish").intern() will return the same instance as simply String s = "fish"

There are two things to remember:

  • never use new String("something")
  • always compare strings with equals(..) (unless you really know what you are doing, and document it)

OTHER TIPS

I think you are looking for String.intern() method which maintains a constant string pool.

The operator '==' compares object references (addresses) while .equals() is a method call which looks at semantic equivalence.

The compiler will look at String a = "fish" and String b = "fish" and then may or may not point to the same address. However, if you do a.intern(); b.intern() then it will probably put them in the same string pool and a == b.

If you're looking for a definitive description, well, go to the definition: JLS § 3.10.5 String Literals.

The example code you should be familiar with is,

Thus, the test program consisting of the compilation unit (§7.3):

package testPackage;
class Test {
        public static void main(String[] args) {
                String hello = "Hello", lo = "lo";
                System.out.print((hello == "Hello") + " ");
                System.out.print((Other.hello == hello) + " ");
                System.out.print((other.Other.hello == hello) + " ");
                System.out.print((hello == ("Hel"+"lo")) + " ");
                System.out.print((hello == ("Hel"+lo)) + " ");
                System.out.println(hello == ("Hel"+lo).intern());
        }
}
class Other { static String hello = "Hello"; }

and the compilation unit:

package other;
public class Other { static String hello = "Hello"; }

produces the output:

true true true true false true
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top