我有以下测试:
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会分配一个和两个指向池中相同的字符串。为什么我的理解在这种情况下是错误的?
答案 0 :(得分:10)
我原本期望由于Java的字符串池特性,VM会分配一个和两个指向池中相同的字符串。
只有字符串常量会自动实现。所以如果您的代码是:
String one = "Hello world";
String two = "Hello " + "world";
...然后one
和two
具有相同的值。因为您使用了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。