【问题标题】:Java comparison with == of two strings is false? [duplicate]Java与两个字符串的==比较是假的? [复制]
【发布时间】:2010-11-03 00:19:50
【问题描述】:

字符串部分是字符串[6]:

[“231”、“CA-California”、“Sacramento-155328”、“aleee”、“客户服务文员”、“Alegra Keith.doc.txt”]

但是当我将parts[0]"231" 进行比较时:

"231" == parts[0]

以上结果为假,

我很困惑,谁能告诉我为什么?

【问题讨论】:

  • @PaulJWilliams - 它确实产生了答案:这个问题。 :)
  • 我想知道为什么数组中的字符串没有被保留,如果数组是使用字符串文字创建的,那么引用比较应该不会成功?
  • Corin 说的:避免“只是尝试谷歌搜索”的 snark,因为在未来,您的 snark 可能实际上是谷歌的热门搜索。就像现在这样。 (并且需要知道这个问题的答案并不意味着你是一个 n00b ......这些天我在这么多编程语言之间切换,我不记得哪些允许我对字符串执行 == 而哪些不允许。在那些不知道的语言中,唯一让我记得正确语法的语言是 C。Java 中有 strcmp 吗?嘿...)
  • 检查是否用new关键字初始化String数组。如果用new关键字初始化String数组它不起作用,因为new总是创建新引用。所以使用这种方式,String[] array= {"231", "CA-California", "Sacramento-155328", "aleee", "Customer Service Clerk", "Alegra Keith.doc.txt"};String str="234";if(str == array [0]){System.out.println("Works");}

标签: java string equals


【解决方案1】:

Java 中的== 比较对象的地址(在这种情况下为字符串)。

你想要的是parts[0].equals("231")

【讨论】:

  • 它比较对象的身份。 可能在内部实现为地址,但 JVM 规范和 JLS 并没有在这里讨论地址。
  • 是的,我也看到了。这是一个挑剔的,但从技术上讲,你不能说它比较地址。 (尽管如果存在任何 以这种方式实现它的 JVM,我会有点震惊......)
【解决方案2】:

== 运算符比较对象引用,而不是 Strings 的值。

要比较Strings 的值,请使用String.equals 方法:

"231".equals(parts[0]);

Java 中的任何其他对象都是如此——比较值时,始终使用equals 方法,而不是使用== 运算符。

equals 方法是Object 的一部分,应该被类覆盖,这些类将以一种或另一种方式进行比较。

【讨论】:

    【解决方案3】:

    使用 equals 方法:parts[0].equals("231")。 == 运算符比较对象引用。

    【讨论】:

      【解决方案4】:

      如果字符串没有被保留,则 == 检查引用标识。使用:

       "231".equals(parts[0]);
      

      改为。

      【讨论】:

      • +1 用于提及字符串文字在相互比较时返回 true。我的一个学生不相信 == 不会检查字符串的实际内容,因为他给我的每个示例都使用字符串文字并返回 true。
      • @Yishai 如果数组是使用字符串字面量创建的,为什么数组中的字符串没有被保留?
      • @Sergio,我想问题是这样设计的,只是列出了数组的内容,而不是它们的创建方式。
      • 我想说的是,如果一个字符串是用:string=new String[]{"231"}[0]; 创建的,它不会被实习,我不知道为什么,因为字符串在代码中是硬编码的(数组使用字符串字面量)。
      • @Sergio,如果您基于这个问题,我认为这实际上并没有发生,只是 OP 以这种方式简化了它。如果你经历过,那我不知道,
      【解决方案5】:

      "==" 比较对象引用,在您的情况下,"231" 是与parts[0] 不同的对象。

      您想使用String.equals

      parts[0].equals("231")
      

      【讨论】:

      • 使用 "foo".equals(bar) 代替 bar.equals("foo") 通常是个好主意。无论 bar 是否为空,第一段代码都将起作用。第二段代码将抛出 NullPointerException。
      【解决方案6】:

      答案很简单:当您通过 == 运算符比较字符串时,实际上是比较两个不同的变量是否引用了一个 String 对象。而不是,数组中的字符串和新创建的“231”是不同的String对象,内容相同。

      正确的做法是使用以下表达式:"231".equals(parts[0])"231".equalsIgnoreCase(parts[0])。如果这些 String 对象包含相同的值,这将为您提供所需的内容并返回 true。

      【讨论】:

        【解决方案7】:

        使用equals方法比较对象:

        String[] test = {"231", "CA-California", "Sacramento-155328", "aleee",
                         "Customer Service Clerk", "Alegra Keith.doc.txt"};
        
        System.out.println("231".equals(test[0]));
        

        比较 '==' 比较的是引用,而不是值。

        【讨论】:

          【解决方案8】:

          我认为在测试用例中表达答案可能会有所帮助:

          public class String231Test extends TestCase {
              private String  a;
              private String  b;
          
              protected void setUp() throws Exception {
                  a = "231";
                  StringBuffer sb = new StringBuffer();
                  sb.append("231");
                  b = sb.toString();
              }
          
              public void testEquals() throws Exception {
                  assertTrue(a.equals(b));
              }
          
              public void testIdentity() throws Exception {
                  assertFalse(a == b);
              }
          }
          

          【讨论】:

            【解决方案9】:

            下面打印出“真”;

            String s = "231";
            if(s == "231")
            {
                System.out.println("true");
            }
            else
            {
                System.out.println("false");
            }
            

            这是因为字符串是不可变的,java 会尽量节省空间,所以它指向同一个内存引用。

            但是,以下打印出“false”:

            String s = new String("231");
            if(s == "231")
            {
                System.out.println("true");
            }
            else
            {
                System.out.println("false");
            }
            

            new 将强制它将字符串存储在新的内存位置。

            顺便说一句,您应该始终使用.equals() 来比较字符串(对于这种情况)

            【讨论】:

            • 因为这不是作者问的,我猜。
            【解决方案10】:

            正如许多其他人已经解释的那样,您尝试与相等运算符进行比较,但随后它将依赖 Object.equals() 而不是 String.equals()。

            所以你可以通过显式调用 String.equals() 来完成这项工作,而不是编写

            parts[0].equals("blahblah")
            

            我更喜欢这样的:

            "blahblah".equals(parts[0])
            

            因为它避免测试parts[0] 的潜在无效性(但要注意parts 变量本身可能为null...)

            另一种方法是使用 String.intern() :

            if (parts[0].intern() == "blahblah") ...
            

            有关更多信息,请参阅http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html#intern()

            【讨论】:

            • 为了使用 == 而对字符串进行内部处理并不是一个好建议,因为它会占用时间和内存。此外,该链接现在已断开。
            【解决方案11】:

            这是一个很好的例子。带有字符串的 '==' 运算符在 Java 中可能非常棘手。

            class Foo {
                public static void main(String[] args) {
                    String a = "hello";
                    String b = "hello";
                    String c = "h";
                    c = c + "ello";
            
                    String operator = null;
            
                    if(a == b) {
                        operator = " == ";
                    } else {
                        operator = " != ";
                    }
            
                    System.out.println(a + operator + b);
            
                    if(a == c) {
                        operator = " == ";
                    } else {
                        operator = " != ";
                    }
            
                    System.out.println(a + operator + c);
            
                    if(a == "hello") {
                        operator = " == ";
                    } else {
                        operator = " != ";
                    }
            
                    System.out.println(a + operator + "hello");
            
                    if(c == "hello") {
                        operator = " == ";
                    } else {
                        operator = " != ";
                    }
            
                    System.out.println(c + operator + "hello");
                }
            }
            

            这将产生以下输出:

            hello == hello
            hello != hello
            hello == hello
            hello != hello
            

            【讨论】:

            • 实际上在任何地方直接使用文字“hello”,它都指向在编译时创建的同一个对象,即所谓的实习字符串,因此 == 的引用相等测试通过,但 c 由运行时并指向其他对象,因此它在引用方面不等于任何“hello”文字。
            【解决方案12】:

            你也可以使用compareTo(String)方法:

            String str = "test";
            
            if( str.compareTo("test") == 0)
               //the argument string is equal to str;
            else
               //the argument string is not equal to str;
            

            【讨论】:

            • 它只比equals() 贵一点,而且并不是真正用于比较平等上的字符串。
            • 说到性能就不得不提hashCode和intern...还有一些例外,compareTo跑得更快。如果两个字符串具有相同的引用或它们具有不同的长度,则等于可以提供更好的性能,但是引用检查和长度检查有时是多余的,例如比较子字符串是否相等。如果两个字符串没有相同的引用(用户输入、子字符串)并且具有相同的长度,compereTo 方法会提供更好的性能。
            猜你喜欢
            • 2017-11-19
            • 1970-01-01
            • 2012-06-19
            • 2012-12-23
            • 2016-10-24
            • 2019-09-08
            • 1970-01-01
            • 2011-05-14
            • 2012-08-02
            相关资源
            最近更新 更多