java中的字符串相等性检查
以下两种说法之间的区别:java中的字符串相等性检查,java,string,memory,hashcode,Java,String,Memory,Hashcode,以下两种说法之间的区别: String s=“你好” String s=新字符串(“Hello”); 在first语句中,赋值运算符用于将字符串文字赋值给字符串变量s。在这种情况下;JVM首先检查字符串常量池中是否已存在相同的对象。如果该对象可用,则会创建对该对象的另一个引用。如果相同的对象为not可用,然后创建另一个内容为“Hello”的对象,并将其存储到字符串常量池中。 在第二条语句中,new操作符用于创建字符串对象。在这种情况下,JVM总是在不查看字符串常量池的情况下创建一个新对象 我对下
String s=“你好”代码>
String s=新字符串(“Hello”);
s
。在这种情况下;JVM
首先检查字符串常量池中是否已存在相同的对象。如果该对象可用,则会创建对该对象的另一个引用。如果相同的对象为not可用,然后创建另一个内容为“Hello”的对象,并将其存储到字符串常量池中。在第二条语句中,
new
操作符用于创建字符串对象。在这种情况下,JVM
总是在不查看字符串常量池的情况下创建一个新对象
我对下面提供的代码的怀疑是语句的输出
System.out.println(a.hashCode() + " " + b.hashCode());
根据规则,这两个对象应该具有不同的内存位置,但它们的hashcode显示为
true
import java.util.HashMap;
import java.util.Map;
class TestStringEquality
{
public static void main (String[] args)
{
String a = new String("abcd");
String b = new String("abcd");
System.out.println(a == b);
System.out.println(a.hashCode() + " " + b.hashCode());
System.out.println(a.equals(b));
Map<String, String> map = new HashMap<>();
map.put(new String("abcd"), "abcd");
map.put(new String("abcd"), "wxyz");
System.out.println(map);
}
}
根据API表
字符串的哈希代码中使用的公式取决于字符串的长度和内容,而不是内存位置。因此,具有不同内存位置的两个相同字符串应给出相同的哈希代码。我认为您混淆了正常堆内存和字符串常量池。当您检查等于时,JVM正在获取g您可以选择存储在普通堆内存中的对象,该对象是一个相同的对象。它们仅在字符串常量池中不同。这就是为什么“==”返回false,因为字符串常量池中的位置不同,因为副本具有不同的引用,但等于返回true,因为这两个副本的类型相同,并且持有相似的字符串。Java有一个conc名为
字符串池的ept
。程序中使用的每个字符串都将作为缓存机制存储在池中
例如下面的代码:
String a = "StackOverFlow"; // Java will push StackOverFlow into string pool
String b = "StackOverFlow"; // Java will get address of "StackOverFlow" object in string pool and assigned to b.
在Java中,程序员不必直接使用指针。然而,指针仍然存在。当使用运算符“==”时,原始数据类型变量如int、short…将按其值进行比较。但在字符串中,Java将按其地址进行比较
这就是以下行返回true的原因:
System.out.println(a == b); // true
String a = "StackOverFlow";
String b = "StackOverFlow"; // use same object as a
String c = new String("StackOverFlow"); // create new string
System.out.println(a.equals(b)); // true
System.out.println(a.equals(b)); // true
System.out.println(a.equals(c)); // true
但是,当您调用新字符串(…)
时,Java将创建一个新的字符串对象。它不会查看字符串池以检查字符串的值是否已存储在字符串池中。这就是两个变量具有相同值的原因,它们的地址仍然不同,因此“==”运算符将返回false
String a = "StackOverFlow";
String b = new String("StackOverFlow"); // new string object. not use old one in String Pool.
System.out.println(a == b); // False. because they have different addresses.
由于字符串池机制,在比较两个对象时,我们必须使用equals
方法。通过这样做,我们不需要关心该字符串对象是如何构建的。因此以下代码始终返回true:
System.out.println(a == b); // true
String a = "StackOverFlow";
String b = "StackOverFlow"; // use same object as a
String c = new String("StackOverFlow"); // create new string
System.out.println(a.equals(b)); // true
System.out.println(a.equals(b)); // true
System.out.println(a.equals(c)); // true
关于hashcode,Java将使用哈希函数从字符串的字符计算值。这样,无论如何构建字符串,如果两个字符串的值相等,它们将具有相同的哈希代码
String a = "StackOverFlow";
String b = "StackOverFlow"; // use same object as a
String c = new String("StackOverFlow"); // create new string
System.out.println(a.hashCode() == b.HashCode()); // true
System.out.println(a.hashCode() == c.HashCode()); // true
通过讨论,我们可以得出以下结论:如果两个字符串具有相同的哈希代码,我们不能确认运算符“==”返回true。因为它们可能是相同的值,但它们是堆内存上的不同对象
但是反之亦然的条件是正确的。如果两个字符串指向相同的地址,它们将具有相同的值,因此具有相同的哈希代码
String a = "StackOverFlow";
String b = "StackOverFlow"; // use same object as a
String c = new String("StackOverFlow"); // create new string
System.out.println(a.hashCode() == b.HashCode()); // true
System.out.println(a.hashCode() == c.HashCode()); // true
有趣的问题:如果两个字符串具有相等的哈希代码,我们可以假定这两个字符串将相等吗?hashCode()实现“Object”类返回底层内存位置 “字符串”的hashCode()实现覆盖对象中的hashCode()。返回此字符串的哈希代码。字符串对象的哈希代码计算为 s[0]*31^(n-1)+s[1]*31^(n-2)+…+s[n-1]
此外,这使程序员的生活更轻松。例如,我们可以使用硬编码的字符串键查询地图,而不是将原始的键对象保留在我们身边。这个字符串等式可以使用hashcode方法。 但是,为了更好地使用性能
String firstString = "string1";
String secondString = "String1";
println(" it will return boolean " + firstString.equal(secondString ) + " "); //false
println(" it will return boolean " + firstString.equalIgnoreCase(secondString ) + " "); //true
如果
a.equals(b)
返回true
,则hashcodes是相同的。在某些IDE中,如果为类生成equals
,它会比较hashcodes。“根据规则,这两个对象应该具有不同的内存位置,但它们的hascode显示为true“--这是一个非sequitor。内存位置与此哈希代码无关。“如果hascode相同,则a==b也应返回true”-错误:如果hascode相同,则equals
也应返回true-“如果hascode相同,则a==b也应返回true”否,对于两个等效实例,hashcode必须相同,但具有相同hashcode的两个实例并不总是等价的。Hashcode只是一个有严格限制的数值。但它不是用来等价的!你的意思是a.equals(b)
,因为a==b
检查对象的引用,而不是值。使用新字符串(String)
没有意义,你为什么要这样做hashCode()
不是内存位置(除非它可能是从Object.hashCode()
-String
的默认实现中派生出来的,所以这与Object.hashCode()
无关)。不.equals()逐字符比较两个字符串,而不是比较堆内存位置?@mihirkekar我只回答了相同的问题:“equals返回true,因为它们都是相同类型的,并且持有相似的字符串。”为了回答最后一个问题,由于int和String的内存限制,可能的字符串比可能的hashcode多得多,因此两个用户可以使用相同的hashcode获得两个不同的字符串。因此,不可能为每个可能的字符串获取唯一的哈希代码。我们可以假设这两个字符串相等吗==