【问题标题】:Comparing two identical strings with == returns false [duplicate]用 == 比较两个相同的字符串会返回 false [重复]
【发布时间】:2011-11-14 13:58:06
【问题描述】:

我正在为我的家人制作档案。没有语法错误,但是每当我输入 "Maaz" 时,它会将 realName == "Maaz" 评估为 false 并转到 else 语句。

import java.util.Scanner;

public class MainFamily {
    public static void main (String [] args) {

        System.out.println("Enter you're name here");
        Scanner name = new Scanner(System.in);//Scanner variable = name

        String realName;
        realName = name.nextLine();//String variable = user input
        System.out.println("Name: "+ realName);

        if (realName == "Maaz") {

            System.out.println("Name: Maaz");

        } else {
            System.out.println("This person is not in the database");
        }
    }
}       

【问题讨论】:

  • 使用realName.equals("Maaz");
  • 一个很好的想法是,提一下,你不会得到编译错误,也没有例外,但是运行时语义错误,等等。但是请阅读关于如何写问题的常见问题解答,创建有意义的标题,而不仅仅是重复标签java 并且您是初学者。发布整个源代码并使用语法突出显示是个好主意,但使用俚语(plzzz)不太好。避免打招呼之类的——几乎这里的每个问题都在寻求帮助。一般来说,欢迎。 :)
  • @GregS:不要滥用 cmets 作为答案。 :)

标签: java string


【解决方案1】:

改为这样做

if (realName.equals("Maaz"))

equals() 应该用于所有非原始对象,例如本例中的字符串

'=='只能在进行原始比较时使用,例如intlong

【讨论】:

    【解决方案2】:

    您必须将对象与realName.equals ("Maaze") 进行比较,而不是与 ==。

    【讨论】:

      【解决方案3】:

      使用

      if(realName.equals("Maaz"))
      

      将 == 与 int boolean .... etc 等原始数据类型一起使用

      但是如果你想在java中比较对象你应该使用equals方法

      【讨论】:

      • 你不应该将==与float和double一起使用(除非你喜欢舍入错误:P)
      【解决方案4】:

      TL;DR

      你写的(这不起作用):

      realName == "Maaz"

      你的意思是:

      realname.equals("Maaz")

      或者这个:

      realname.equalsIgnoreCase("Maaz")

      说明

      在 Java(和许多其他面向对象的编程语言)中,对象与数据类型不同。数据类型被运行时识别为数据类型。

      数据类型示例包括:int、float、short。

      没有与数据类型关联的方法或属性。例如,这会引发错误,因为数据类型不是对象:

      int x = 5;
      int y = 5;
      if (x.equals(y)) {
          System.out.println("Equal");
      }
      

      引用基本上是一块内存,它明确地告诉运行时环境该数据块是什么。运行时不知道如何解释它;它假定程序员会这样做。

      例如,如果我们在前面的示例中使用 Integer 而不是 int,这将起作用:

      Integer x = new Integer(5);
      Integer y = new Integer(5);
      if (x.equals(y)) {
          System.out.println("Equal");
      }
      

      而这不会给出预期的结果(if 条件将评估为假):

      Integer x = new Integer(5);
      Integer y = new Integer(5);
      if (x == y) {
          System.out.println("Equal");
      }
      

      这是因为两个 Integer 对象具有相同的值,但它们不是同一个对象。双等号基本上检查两个对象是否是相同的引用(有其用途)。

      在您的代码中,您将一个对象与一个字符串文字(也是一个对象)进行比较,这与比较两者的值不同。

      让我们看另一个例子:

      String s = "Some string";
      if (s == "Some string") {
          System.out.println("Equal");
      }
      

      在这种情况下,if 块可能会评估为 true。这是为什么呢?

      编译器经过优化,可以使用尽可能少的额外内存,尽管这意味着什么取决于实现(可能还有运行时环境)。

      第一行中的字符串文字"Some string" 可能会被识别为等同于第二行中的字符串文字,并且将在内存中使用相同的位置。简单来说,它将创建一个 String 对象并将其插入“Some string”的两个实例中。这是不可靠的,因此如果您只关心值,则使用 String.equals 始终是检查等价性的更好方法。

      【讨论】:

      • 好答案。有关更多相关信息,请参阅此问题:stackoverflow.com/questions/594604/…
      • 如果我没记错的话,Java 已经为整数预分配了 0-255,因此所有值在该范围内的整数实际上都是相等的,因为它们都指向同一个对象......类似地,final 字符串 s1 = "foo"; final String s2 = "foo"; 也是相等的,因为它们将被优化为指向同一个对象。
      • @Paxinum - 这就是我上一个代码示例想要表达的意思,但我不确定每个运行时/编译器是否都工作相同(例如 OpenJDK、Android 的编译器等)。
      • 但是如果像这样的条件String s1 = new String("test"); String s2 = "test"; s1 == s2 总是会返回false
      【解决方案5】:

      == 测试浅层相等。它检查两个对象是否引用内存中的相同位置。

      【讨论】:

      • == 测试 instance 是否相等。它可能通过比较内存位置来做到这一点,这是一些 JVM 的实现细节,不一定是真的。
      【解决方案6】:

      你也可以使用

      realname.equalsIgnoreCase("Maaz")
      

      这样就可以接受 Maaz、maaz、maaZ、maaZ 等。

      【讨论】:

      • 如果 (mystring.equals("test")==false 会起作用
      【解决方案7】:

      有趣。虽然,正如其他人所说,正确的方法是使用 .equals(...) 方法,但我一直认为字符串是池化的(不管它们是如何创建的)。似乎这仅适用于字符串文字。

      final String str1 = new String("Maaz");
      final String str2 = new String("Maaz");
      System.out.println(str1 == str2); // Prints false
      
      final String str3 = "Laaz";
      final String str4 = "Laaz";
      System.out.println(str3 == str4); // Prints true
      

      【讨论】:

      • 字符串文字的相等性在 JLS,第 3.10.5 章中是众所周知的并且定义明确:String Literals
      • 第一部分测试str1str2 的身份(位置),因此它们不指向内存中的相同位置。第二部分测试字符串文字并测试它们的值(这是池/实习发挥作用的地方。
      • @non - 嗯?这两部分都完全相同。字符串文字是实习的,因此 str3str4 具有相同的值;它们都指向内存中的同一个地方。
      • @non == for objects 比较参考值。我同意布赖恩的观点。
      【解决方案8】:

      最佳实践是使用str.equals(str2) 而不是str == str2 比较字符串。正如您所观察到的,第二种形式在很多时候都不起作用。相比之下,第一种形式总是有效

      == 方法始终有效的唯一情况是在比较字符串时:

      • 字符串文字或对字符串文字的引用,或
      • 已被应用程序级代码调用str = str.intern();“实习”的字符串。

      (不,默认情况下不保留字符串。)

      由于编写程序来保证所有字符串的这些先决条件通常很棘手,因此最佳实践使用equals,除非有与性能相关的必要性来实习你的字符串并使用@ 987654326@.

      在您决定实习是个好主意之前,您需要比较实习的好处和成本。这些成本包括在字符串池的哈希表中查找字符串的成本以及维护字符串池的空间和 GC 开销。与仅使用常规字符串和使用 equals 进行比较的典型成本相比,这些成本并不小。

      【讨论】:

      • 为了完整起见:在这种情况下,像 "hello " + "world" 这样的字符串值常量表达式的行为方式与字符串文字相同。
      • @JohnC - 这是真的,但它(IMO)与问题或我的答案都不相关。特别是因为我的回答的 主要消息 是不使用 == 来比较字符串。
      【解决方案9】:

      由于您正在处理字符串,因此您应该使用 String 类的 equals to equalsIngnorecase 方法。 "==" 只会比较两个对象指向相同的内存位置,在您的情况下,两个对象不同并且不会相等,因为它们不指向相同的位置。另一方面,String 类的 equals 方法根据对象包含的值进行比较。因此,如果您将使用 equals 方法,则您的 if 条件将得到满足。

      【讨论】:

        【解决方案10】:

        == 比较对象引用原始类型(int、char、float ...)

        equals(),你可以重写这个方法来比较两个对象是否相等。

        对于String类,其方法equal()会比较里面的内容是否相同。

        如果您的示例,两个字符串没有相同的对象引用,因此它们返回 false,== 不比较两个字符串上的字符。

        【讨论】:

          【解决方案11】:

          似乎还没有人指出,在 Java 中比较对象和常量的最佳做法是调用常量的 equals 方法,而不是变量对象:

          if ("Maaz".equals (realName)) {}
          

          这样你就不需要额外检查变量 realName 是否为空。

          【讨论】:

          • There are no Best Practices。在realNamenull 的情况下是错误的症状,那么您希望发生NPE,以便您知道错误存在。在这种情况下,这种(所谓的)最佳实践不是正确的解决方案。因此,这根本不是最佳实践。
          【解决方案12】:
          if(realName.compareTo("Maaz") == 0) {
              // I dont think theres a better way do to do this.
          }
          

          【讨论】:

            猜你喜欢
            • 2016-12-18
            • 2016-04-17
            • 2019-10-06
            • 1970-01-01
            • 2011-12-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多