7

可能重复:
Java 字符串和 StringPool

我创建了两个字符串

String s1="MyString";
String s2=new String("MyString");
System.out.println(s1==s2);

它打印"false"。我们知道字符串池不会为同一个字符串字面量创建两个对象。

那么这里发生了什么?它在字符串池中为相同的字符串文字“MyString”创建了两个不同的字符串对象(文字)。

我知道 equals()方法true在这里返回。

但是当我们使用==它时应该比较两个引用,它们应该引用字符串常量池中的同一个字符串对象。

为什么即使找到匹配项,它也没有引用字符串池中现有的字符串对象?

4

5 回答 5

14

第一个进入池,而第二个存储在堆中。

使用s2 = s2.intern();使其返回true

当您intern()对字符串执行操作时,JVM 会确保字符串存在于池中。如果它尚不存在,则会在池中创建它。否则,返回已经存在的实例。我认为这解释了这种==行为。

String s1="MyString";
String s2=new String("MyString");
s2 = s2.intern();
System.out.println(s1==s2);

作为参考,以下是String.intern()文档中的内容:

/**
 * Returns a canonical representation for the string object.
 * <p>
 * A pool of strings, initially empty, is maintained privately by the
 * class <code>String</code>.
 * <p>
 * When the intern method is invoked, if the pool already contains a
 * string equal to this <code>String</code> object as determined by
 * the {@link #equals(Object)} method, then the string from the pool is
 * returned. Otherwise, this <code>String</code> object is added to the
 * pool and a reference to this <code>String</code> object is returned.
 * <p>
 * It follows that for any two strings <code>s</code> and <code>t</code>,
 * <code>s.intern()&nbsp;==&nbsp;t.intern()</code> is <code>true</code>
 * if and only if <code>s.equals(t)</code> is <code>true</code>.
 * <p>
 * All literal strings and string-valued constant expressions are
 * interned. String literals are defined in section 3.10.5 of the
 * <cite>The Java&trade; Language Specification</cite>.
 *
 * @return  a string that has the same contents as this string, but is
 *          guaranteed to be from a pool of unique strings.
 */
public native String intern();
于 2012-08-20T12:04:43.223 回答
6

String s2=new String("MyString");您正在创建 的实例的行中String,因此它肯定不会与s1.

如果你这样做:

System.out.println(s1=="MyString");

你会得到true.

于 2012-08-20T12:04:21.413 回答
3

s2不是字符串文字,它是从一个使用时构造的new- 但它不是文字,它是一个新对象。

于 2012-08-20T12:04:30.533 回答
3

实际上,您正在创建两个不同的对象,一个在Literal Pool其中,一个在Heap

String s1 = "MyString"; //literal pool
String s2 = new String("MyString"); //in heap
s.o.p(s1==s2); // false, because two different instances
s.o.p(s1.equals(s2)); // true, compares the contents of the string.

您需要equals改用==. 您可以通过调用将字符串对象从堆推送到字符串字面量池(或常量池)String.intern()

于 2012-08-20T12:06:44.970 回答
0

字符串池不是创建两个实例,而是创建第二个String实例的构造函数调用。来自String(String original)的 javadoc :

初始化一个新创建的 String 对象,使其表示与参数相同的字符序列;换句话说,新创建的字符串是参数字符串的副本。除非需要原始的显式副本,否则不需要使用此构造函数,因为字符串是不可变的。

因此,由于您正在创建第二个实例==正确返回false(并且equals(Object anObject)将返回true)。

于 2012-08-20T12:12:15.903 回答