5

I am trying to understand Java's String class but I am having a hard time understanding the situation described below.

Consider the following example snippet:

String x = new String("Hey");
String y = "Hey";

If I use bool = y == x.intern(); the variable bool will equal true.

My question is:

When I make a declaration like this:

String b = "h";
String a = b.intern + "ey";
boolean x = a == "hey";

x's value would be false but when I make a = (b + "ey").intern(); x's value will be true.

Why won't x = true in the second example? Is it because the declarations in the first example not alike? If yes what are the differences?

acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • The following link may be helpful to you: https://weblogs.java.net/blog/2006/06/26/all-about-intern – PM 77-1 Jul 23 '13 at 22:04
  • 1
    `String + String` evaluates to a new String which is *not* magically interned: it does not try to find existing interned Strings with the same content. Now, if both String expressions are literals then the entire expression might be *folded* during compilation - which means only the *result* is found in the compiled output and is subject to standard intern rules - but that leads to a different cute case: `("h" + "ey") == "hey"` is true. As soon as folding is *eliminated* (i.e. with a variable) this goes away. – user2246674 Jul 23 '13 at 22:07
  • @TariqAyman I did some edits to your question, trying to improve its formatting. Please review it if you feel any point of your question was lost. – acdcjunior Jul 23 '13 at 22:08
  • You might want to check this related answer http://stackoverflow.com/a/513839/422353 – madth3 Jul 23 '13 at 22:09

3 Answers3

5

With your first example:

String y = "Hey";

Java automatically interns string literals such as this (JLS section 3.10.5):

Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.

So when you call x.intern(), you get the interned copy of "Hey", so they are the same object and == returns true.

But in the second example, b.intern() is a method call that is evaluated at runtime, and Java's concatenation operator will return a new String (not interned), which is a different object than the string literal "hey" (interned already), so == returns false (different objects).

EDIT

To clear up what happens with the string concatenation, turn to JLS Section 15.18.1:

The result of string concatenation is a reference to a String object that is the concatenation of the two operand strings. The characters of the left-hand operand precede the characters of the right-hand operand in the newly created string.

The String object is newly created (§12.5) unless the expression is a compile-time constant expression (§15.28).

But, b.intern() + "ey"; is not a compile-time constant expression, so the resultant String object has not been interned, and == will detect that it's a different object than the interned "hey".

rgettman
  • 176,041
  • 30
  • 275
  • 357
  • Thank for clearing it out but if you make a new String like b = "h" + "ey" this is a concatenated String but it will equal "hey" is it because there are no objects ? – Tariq Ayman Jul 23 '13 at 22:08
  • The compiler optimizes out the `+` and automatically interns the result. – Lee Meador Jul 23 '13 at 22:09
  • 1
    @LeeMeador That's true for a compile-time constant expression such as `"h" + "ey"`, but not for something involving a method call, such as `b.intern() + "ey"`. – rgettman Jul 23 '13 at 22:13
  • Yes. Maybe I didn't make it clear my last comment referred to OP's questions about "h" + "ey". – Lee Meador Jul 23 '13 at 22:20
3

This one creates a string and stores it:

String a = b.intern() + "ey";

This one creates a string, interns it and stores the interned version:

String a = (b + "ey").intern();

All interned strings with the same content are ==

All string literals (strings supplied in the form "hey") are interned by the compiler internally.

Strings that are not interned but have the same content are only equal() and not ==

For posterity, one more ... where the compiler optimizes out the + resulting in "hey" and interns it just as it would the string literal "hey"

String a = "h" + "ey";
Lee Meador
  • 12,829
  • 2
  • 36
  • 42
0

Java concatenates Strings by using a StringBuilder:

b.intern() + "ey" turns into something similar to
new StringBuilder(b.intern()).append("ey").toString(). This creates a new String, so it will not be == to "hey".

Jeffrey
  • 44,417
  • 8
  • 90
  • 141