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”);

  • first语句中,赋值运算符用于将字符串文字赋值给字符串变量
    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获得两个不同的字符串。因此,不可能为每个可能的字符串获取唯一的哈希代码。我们可以假设这两个字符串相等吗==