Java 字符串池的意外行为
我有以下测试:Java 字符串池的意外行为,java,string-comparison,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!!! assert
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会分配一个和两个指向池中相同字符串的字符串。为什么在这种情况下我的理解是错误的?每当您使用new操作符时,总是在Heap上创建一个新对象。因此,即使字符串helloworld在文本池中可用,它也不会被引用。事实上,您正在堆上创建4个对象:-
Hello World-->新字符串Hello World;
Hello-->新建StringHello;
世界-->新世界;
同样,Hello World-->新建StringHello+新建StringWorld;
除此之外,在文字池中还会创建3个文字-Hello World、Hello和World
总共有7个对象
另一方面,您是否使用以下方法创建了字符串:-
String str = "Hello World";
String str2 = "Hello " + "World";
同样,这里将在文字池上创建3个文字-Hello World、Hello和World,但最后两个文字的串联将引用第一个文字
因此,两个字符串引用指向相同的文本,因此它们现在将相等。每当您使用new操作符时,总是在Heap上创建一个新对象。因此,即使字符串helloworld在文本池中可用,它也不会被引用。事实上,您正在堆上创建4个对象:-
Hello World-->新字符串Hello World;
Hello-->新建StringHello;
世界-->新世界;
同样,Hello World-->新建StringHello+新建StringWorld;
除此之外,在文字池中还会创建3个文字-Hello World、Hello和World
总共有7个对象
另一方面,您是否使用以下方法创建了字符串:-
String str = "Hello World";
String str2 = "Hello " + "World";
同样,这里将在文字池上创建3个文字-Hello World、Hello和World,但最后两个文字的串联将引用第一个文字
因此,两个字符串引用指向相同的文本,因此它们现在是相等的
我原以为,由于Java的字符串池性质,VM会分配一个和两个指向池中相同字符串的字符串
只有字符串常量会自动插入。因此,如果您的代码是:
String one = "Hello world";
String two = "Hello " + "world";
。。。那么1和2的值就相同了。因为您使用了新的字符串…,所以这些表达式不是常量表达式,所以它们不是临时表达式。当然,这些文字仍然被拘留。。。但不是从文本创建的字符串
有关常量表达式的详细信息,请参见
我原以为,由于Java的字符串池性质,VM会分配一个和两个指向池中相同字符串的字符串
只有字符串常量会自动插入。因此,如果您的代码是:
String one = "Hello world";
String two = "Hello " + "world";
。。。那么1和2的值就相同了。因为您使用了新的字符串…,所以这些表达式不是常量表达式,所以它们不是临时表达式。当然,这些文字仍然被拘留。。。但不是从文本创建的字符串
有关常量表达式的详细信息,请参阅。每当使用新字符串xyz创建字符串对象时,都会创建一个新的对象引用 例如:当您只处理文本时,将使用字符串池性质
String one = "Hello world";
String two = "Hello "+ "world";
System.out.println(one==two);
将打印为true。每当使用新字符串xyz创建字符串对象时,将创建一个新的对象引用 例如:当您只处理文本时,将使用字符串池性质
String one = "Hello world";
String two = "Hello "+ "world";
System.out.println(one==two);
将打印为真。我数了4个以上:Hello-world-literal,一个对象,两个对象,Hello-literal,world-literal,new-StringHello-object和new-Stringworld-object=>我会说7个对象。@assylias。是的,我漏掉了文字。谢谢:或者你可以用+=操作符更简洁一些。@TheBlueCat和where确切位置?String str=Hello;字符串str2+=世界;我数了4个以上:Hello-world-literal,1个对象,2个对象,Hello-literal,world-literal,new-StringHello-object和new-Stringworld-object=>我会说7个对象。@assylias。是的,我漏掉了文字。谢谢:或者你可以用+=操作符更简洁一些。@TheBlueCat和where确切位置?String str=Hello;字符串str2+=世界;那不是复制品。这个问题是关于字符串实习的。@RobertHarvey你是对的,答案有点重复,但我猜不是重复的问题。值得注意的是:在C中,这是正确的,因为在大多数情况下比较两个字符串的引用并不是特别有意义。请看。@RobertHarvey那么,在C语言中,谁比较了对对象的引用呢?这似乎比Java as==更落后,只是比较了String.class中的方法,该方法由Object class.equals覆盖,用于测试值是否相等。这在C语言中是一样的吗?对不起,我离题了,我只是有点困惑。@TheBlueCat:为了比较引用,你可以使用。要点是,在C中,==用于比较两个字符串的更常见场景
一封接一封,这不是重复的。这个问题是关于字符串实习的。@RobertHarvey你是对的,答案有点重复,但我猜不是重复的问题。值得注意的是:在C中,这是正确的,因为在大多数情况下比较两个字符串的引用并不是特别有意义。请看。@RobertHarvey那么,在C语言中,谁比较了对对象的引用呢?这似乎比Java as==更落后,只是比较了String.class中的方法,该方法由Object class.equals覆盖,用于测试值是否相等。这在C语言中是一样的吗?对不起,我离题了,我只是有点困惑。@TheBlueCat:为了比较引用,你可以使用。关键是,在C中,==用于更常见的场景,即逐字母比较两个字符串。