字符串池的意外行为

时间:2012-10-22 16:07:05

标签: java string-comparison

我有以下测试:

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()));
    }
}

我原本预计由于Java的字符串池特性,VM会分配一个和两个指向池中相同的字符串。为什么我的理解在这种情况下是错误的?

3 个答案:

答案 0 :(得分:10)

  

我原本期望由于Java的字符串池特性,VM会分配一个和两个指向池中相同的字符串。

只有字符串常量会自动实现。所以如果您的代码是:

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

...然后onetwo具有相同的值。因为您使用了new String(...),所以这些表达式不是常量表达式,因此它们不会被实现。 (文字当然仍然是实习的......但不是文字创建的字符串。)

有关计算为常量表达式的详细信息,请参阅section 15.28 of the JLS

答案 1 :(得分:4)

每当您使用 new operator 时,总会在上创建一个新对象。因此,即使 Literal Pool 中有String “Hello World”,也不会引用它。所以实际上你是在上创建 4个对象: -

  • Hello World ----> new String("Hello World");
  • Hello ----> new String("Hello");
  • World ----> new String("World");
  • 再次,Hello World ----> new String("Hello") + new String("World");

除了他们之外,还会在 Literal Pool 上创建 3文字 - “Hello World”,“Hello”和“World”

所以,总共 7个对象


另一方面,您是否使用以下方式创建了字符串: -

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

同样,这里 3文字将在 Literal Pool - “Hello World”,“Hello”和“World”上创建,但最后两个文字的串联将引用第一个文字

因此two String引用点指向同一literals,因此它们现在相等

答案 2 :(得分:0)

每当使用new String(“xyz”)创建String对象时,都会创建一个新的对象引用。

例如:当您处理文字时,将使用字符串池性质。

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

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

将打印为true。