Java Reference
In-Depth Information
String
boat
=
sb
.
toString
();
System
.
out
.
println
(
boat
);
Code like this is equivalent to what
javac
would generate if, instead, we had written:
String
pet
=
"Cat"
;
String
boat
=
pet
+
"amaran"
;
System
.
out
.
println
(
boat
);
Of course, as well as being used under the hood by
javac
, the
StringBuilder
class
can also be used directly in application code, as we've seen.
Along with
StringBuilder
Java also has a
StringBuffer
class. This comes from the oldest versions of Java, and
should not be used for new development—use
String
Builder
instead, unless you really need to share the con‐
struction of a new string between multiple threads.
String immutability is an extremely useful language feature. For example, suppose
the
+
changed a string instead of creating a new one; then whenever any thread con‐
catenated two strings together, all other threads would also see the change. This is
unlikely to be a useful behavior for most programs, and so immutability makes
good sense.
Hash codes and efective immutability
We have already met the
hashCode()
method in
Chapter 5
, where we described the
contract that the method must satisfy. Let's take a look at the JDK source code and
see how the method
String::hashCode()
is defined:
public
int
hashCode
()
{
int
h
=
hash
;
if
(
h
==
0
&&
value
.
length
>
0
)
{
char
val
[]
=
value
;
for
(
int
i
=
0
;
i
<
value
.
length
;
i
++)
{
h
=
31
*
h
+
val
[
i
];
}
hash
=
h
;
}
return
h
;
}
The field
hash
holds the hash code of the string, and the field
value
is a
char[]
that
holds the characters that actually make up the string. As we can see from the code,
the hash is computed by looping over all the characters of the string. It therefore
takes a number of machine instructions proportional to the number of characters in
the string. For very large strings this could take a bit of time. Rather than pre-
compute the hash value, Java only calculates it when it is needed.