1

I have the following Test:

public class EqualityTest
{
    String one = new String("Hello world");
    String two = new String("Hello ") + new String("world");

    @Test
    public void testStringPool()
    {
        assertFalse(one == two); // FALSE!!!
        assertTrue(one.equals(two));
        assertTrue(one.intern().equals(two.intern()));
    }
}

I would have expected that due to the String pool nature of Java, the VM would allocated one and two pointing to the same String in the pool. Why is my understanding wrong in this case?

Baz
  • 36,440
  • 11
  • 68
  • 94
  • 2
    That's not a duplicate. This question is about string interning. – Robert Harvey Oct 22 '12 at 16:13
  • @RobertHarvey You are right, sort of duplicate answer but not duplicate question I guess. – assylias Oct 22 '12 at 16:14
  • Worth noting: in C#, this works correctly, as comparing the reference of two strings is not particularly meaningful in the majority of cases. See http://stackoverflow.com/questions/1659097/c-string-equals-vs. – Robert Harvey Oct 22 '12 at 16:18
  • @RobertHarvey Who do you compared reference to objects in C# then? That seems backward (even more so than Java) as `==` just compared references the method in String.class, which is overridden from Object the Object class (.equals) test for value equality. Is this the same in C# - sorry for being off topic, I'm just puzzeled. – TheBlueCat Oct 22 '12 at 16:59
  • @TheBlueCat: For comparing references, you can use [`ReferenceEquals()`](http://msdn.microsoft.com/en-us/library/system.object.referenceequals%28v=vs.71%29.aspx). The point is, in C#, `==` is used for the more common scenario of comparing two strings letter by letter. – Robert Harvey Oct 22 '12 at 17:03
  • @RobertHarvey So there's two 'ways' to test for equal value? – TheBlueCat Oct 22 '12 at 17:06
  • @TheBlueCat: Yes, `==` and `Equals()` work the same for strings. See http://msdn.microsoft.com/en-en/library/362314fe.aspx. It says, *"Although string is a reference type, the equality operators (== and !=) are defined to compare the values of string objects, not references. This makes testing for string equality more intuitive."* – Robert Harvey Oct 22 '12 at 17:12

3 Answers3

10

I would have expected that due to the String pool nature of Java, the VM would allocated one and two pointing to the same String in the pool.

Only string constants are interned automatically. So if your code had been:

String one = "Hello world";
String two = "Hello " + "world";

... then one and two would have had the same value. Because you've used new String(...), these expressions aren't constant expressions, and so they aren't interned. (The literals are still interned, of course... but not the strings created from the literals.)

See section 15.28 of the JLS for details on what counts as a constant expression.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
4

Whenever you use new operator, a new object is always created on Heap. So, even if the String "Hello World" is available in the Literal Pool, it will not be referenced. So in fact you are creating 4 objects on Heap: -

  • Hello World ----> new String("Hello World");
  • Hello ----> new String("Hello");
  • World ----> new String("World");
  • And again, Hello World ----> new String("Hello") + new String("World");

Apart from them, there would be 3 literals created on Literal Pool - "Hello World", "Hello" and "World"

So, 7 objects in total.


On the other hand, had you created your Strings using: -

String str = "Hello World";
String str2 = "Hello " + "World";

Again, here 3 literals would be created on Literal Pool - "Hello World", "Hello " and "World", but the concatenation of the last two literals will reference the first literal.

And hence the two String reference point to same literals, and hence they would be equal now.

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
0

Whenever new String ("xyz") is used for creating String object, a new object reference will be created.

For example : when you are dealing with just literals then String pool nature will be used.

String one = "Hello world";
String two = "Hello "+ "world";

System.out.println(one==two);

will print true.

Metalhead
  • 1,429
  • 3
  • 15
  • 34