我创建了两个字符串
String s1="MyString";
String s2=new String("MyString");
System.out.println(s1==s2);
打印"false"
。我们知道字符串池不会为同一个字符串文字创建两个对象。
那么这里发生了什么?它在字符串池中为相同的字符串文字“MyString”创建两个不同的字符串对象(文字)。
我知道equals()
方法在这里返回true
。
但是当我们使用==
时,它应该比较两个引用,它们应该引用相同的引用
String常量池中的String对象。
为什么即使找到匹配项,它也没有引用String池中的现有String对象?
答案 0 :(得分: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() == 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™ 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();
答案 1 :(得分:6)
在String s2=new String("MyString");
行中,您正在创建String
的新实例,因此它肯定不会与s1
的实例相同。< / p>
如果你这样做:
System.out.println(s1=="MyString");
您将获得true
。
答案 2 :(得分:3)
s2
不是字符串文字,它是在使用new
时从一个构造的 - 但它不是文字,它是一个新对象。
答案 3 :(得分: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()
将字符串对象从堆推送到String文本池(或常量池)。
答案 4 :(得分:0)
String池没有创建两个实例,它是构造函数调用,用于创建第二个String
实例。来自String(String original)的javadoc:
初始化一个新创建的String对象,使其表示与参数相同的字符序列;换句话说,新创建的字符串是参数字符串的副本。除非需要显式的原始副本,否则不必使用此构造函数,因为字符串是不可变的。
因此,由于您正在创建第二个实例==
,因此正确返回false
(而equals(Object anObject)将返回true
)。