Table 4-4 reveals a couple of interesting items about String . First, this class's
String(String s) constructordoesnotinitializea String objecttoastringliter-
object to the contents of another String object. This behavior suggests that a string
literal is more than what it appears to be.
In reality, a string literal is a String object. You can prove this to yourself by
executing System.out.println("abc".length()); and Sys-
tem.out.println("abc" instanceof String); .Thefirstmethodcallout-
puts 3 ,whichisthelengthofthe "abc" String object'sstring,andthesecondmeth-
od call outputs true ( "abc" is a String object).
Note String literals are stored in a classfile data structure known as the constant
pool .Whenaclassisloaded,a String objectiscreatedforeachliteralandisstored
in an internal table of String objects.
Thesecondinterestingitemisthe intern() method,which interns (storesaunique
copyof)a String objectinaninternaltableof String objects. intern() makes
itpossibletocomparestringsviatheirreferencesand == or != .Theseoperatorsarethe
By default, String objects denoted by literal strings ( "abc" ) and string-valued
constant expressions ( "a"+"bc" ) are interned in this table, which is why Sys-
tem.out.println("abc" == "a"+"bc"); outputs true .However, String
objects created via String constructors are not interned, which is why Sys-
tem.out.println("abc" == new String("abc")); outputs false .
In contrast, System.out.println("abc"
String("abc").intern()); outputs true .
Caution Be careful with this string comparison technique (which only compares
references) because you can easily introduce a bug when one of the strings being
compared has not been interned. When in doubt, use the equals() or
Table 4-4 also reveals the charAt() and length() methods, which are useful
for iterating over a string's characters. For example, String s = "abc"; for
(int i = 0; i < s.length(); i++) Sys-
tem.out.println(s.charAt(i)); returns each of s 's a , b , and c characters
and outputs each character on a separate line.