Strings and Equality


The String class is optimized for heavy use. In most applications, the number of String objects created vastly outweighs the number of any other type being created.

The current version of the Java VM provides a set of command-line switches to turn on various types of profiling. You can enter:

 java -agentlib:hprof=help 

at the command line for further details.[10]

[10] This feature is not guaranteed to be part of future versions of Java.

I ran a heap profile against the JUnit run of the current suite of almost 60 tests. The Java VM created about 19,250 objects in the fraction of the second required to run the tests. Out of those objects, over 7,100 were String objects. The object count for the next most frequently instantiated type was around 2,000. Counts dropped off dramatically after that.

These numbers demonstrate the key role that the String class plays in Java. String objects will account for a third to over a half of all objects created during a typical application execution. As such, it is critical that the String class perform well. It is also critical that the creation of so many strings does not bloat the memory space.

To minimize the amount of memory used, the String class uses a literal pool. The main idea is that if two String objects contain the same characters, they share the same memory space (the "pool"). The String literal pool is an implementation of a design pattern called Flyweight.[11] Flyweight is based on sharing and is designed for efficient use of large numbers of fine-grained objects.

[11] [Gamma1995].

To demonstrate:

 String a = "we have the technology"; String b = "we have the technology"; assertTrue(a.equals(b)); assertTrue(a == b); 

The strings a and b are semantically equal (.equals): Their character content is the same. The string references also have memory equivalence (==): They point to the same String object in memory.

Because of this optimization, as a beginning Java programmer it is easy to think you should compare String objects using ==.

 if (name == "David Thomas") 

But this is almost always a mistake. It is possible for two strings to contain the same characters but not be stored in the same memory location. This occurs because Java cannot optimize Strings that are constructed through the use of StringBuilder or concatenation.[12]

[12] When compiled, code using the + for String concatenation translates to equivalent code that uses the StringBuffer class.

Compare Strings using equals, not ==.


 String c = "we have"; c += " the technology"; assertTrue(a.equals(c)); assertFalse(a == c); 

This test passes. The Java VM stores c in a different memory location than a.

You might be able to compare String objects using == in certain controlled circumstances in your code. Doing so can provide a boost in performance. However, you should use == for a String comparison only as a performance optimization and document it as such with explicit comments. Being clever and using memory equivalence comparisons for String in other circumstances is a great way to invite insidious bugs that are difficult to track down.



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net