String.equals与==的区别

584

这段代码将一个字符串分解成令牌,并将它们存储在一个字符串数组中,然后将一个变量与第一个home进行比较......为什么它不起作用?

public static void main(String...aArguments) throws IOException {

    String usuario = "Jorman";
    String password = "14988611";

    String strDatos = "Jorman 14988611";
    StringTokenizer tokens = new StringTokenizer(strDatos, " ");
    int nDatos = tokens.countTokens();
    String[] datos = new String[nDatos];
    int i = 0;

    while (tokens.hasMoreTokens()) {
        String str = tokens.nextToken();
        datos[i] = str;
        i++;
    }

    //System.out.println (usuario);

    if ((datos[0] == usuario)) {
        System.out.println("WORKING");
    }
}

2
请看一下这个链接:http://www.thejavageek.com/2013/07/27/string-comparison-with-equals-and-assignment-operator/ - Prasad Kharkar
3
"=="比较的是引用而不是内容。将"datos[0] == usuario"改为"datos[0].equals(usuario)"可以得到正确的答案。" - mani deepak
2
我看到你改变了你接受的答案 - 我敦促你阅读我的评论并重新考虑。现在被接受的答案中的“故事”可能一开始看起来不错,但在我看来,它真的经不起审查。 - Alnitak
大多数语言都是这样工作的,只是你看不到,因为大多数语言都有运算符重载,而字符串的==运算符已被重载以调用语言等效的string.equals。Java没有运算符重载,所以你必须像穴居人一样费力地去做。Java在比较字符串时也不会抱怨或警告你,所以它变成了一个运行时错误,你需要去追踪。为什么Java没有运算符重载?因为他们想保持语言简单,然后他们意识到它太简单了,使得处理日期变得复杂。 - LordWabbit
20个回答

9

如果您要比较任何字符串的赋值,即原始字符串,"=="和.equals都可以使用,但对于新的字符串对象,您应该只使用.equals,这里"=="不起作用。

例如:

String a = "name";

String b = "name";

if(a == b)(a.equals(b)) 会返回 true。

但是,

String a = new String("a");

在这种情况下,if(a == b)将返回false。因此最好使用.equals运算符...

8

==运算符在Java中比较对象的引用。您可以使用字符串的equals方法。

String s = "Test";
if(s.equals("Test"))
{
    System.out.println("Equal");
}

8

通常使用.equals进行Object比较,您想要验证两个Objects是否具有相同的值。

==用于引用比较(这两个Objects在堆上是相同的Object)和检查Object是否为null。它还用于比较基本类型的值。


6

@Melkhiah66 您可以使用equals方法而不是“==”方法来检查相等性。 如果您使用intern(),则它会检查对象是否在池中,如果存在,则返回相等,否则不相等。 equals方法在内部使用hashcode并为您提供所需的结果。

public class Demo
{
  public static void main(String[] args)
  {
              String str1 = "Jorman 14988611";
    String str2 = new StringBuffer("Jorman").append(" 14988611").toString();
    String str3 = str2.intern();
    System.out.println("str1 == str2 " + (str1 == str2));           //gives false
    System.out.println("str1 == str3 " + (str1 == str3));           //gives true
    System.out.println("str1 equals str2 " + (str1.equals(str2)));  //gives true
    System.out.println("str1 equals str3 " + (str1.equals(str3)));  //gives true
  }
}


6
我知道这是一个老问题,但以下是我的看法(我发现非常有用):

技术解释

在Java中,所有变量都是原始类型引用类型

(如果您需要了解引用是什么:“对象变量”只是指向对象的指针。因此,使用Object something = ...,something实际上是内存中的地址(一个数字)。)

==比较确切的值。因此,它比较原始值是否相同,或者引用(地址)是否相同。这就是为什么==经常不能在字符串上工作的原因;字符串是对象,对两个字符串变量执行==仅会比较内存中的地址是否相同,正如其他人所指出的那样。.equals()调用对象的比较方法,该方法将比较由引用指向的实际对象。对于字符串,它将比较每个字符以查看它们是否相等。


有趣的部分

那么为什么==有时会对字符串返回true?请注意,字符串是不可变的。在您的代码中,如果您执行

String foo = "hi";
String bar = "hi";

由于字符串是不可变的(当你调用.trim()或其他操作时,它会生成一个新的字符串,而不是修改内存中指向原始对象的位置),因此你实际上不需要两个不同的String("hi")对象。如果编译器很聪明,字节码将只读取以生成一个String("hi")对象。所以如果你这样做:

if (foo == bar) ...

一旦出现这种情况,它们就指向相同的对象,并返回true。但你很少会想要这样做。相反,你正在请求用户输入,这将在内存的不同部分创建新的字符串等等。
注意:如果你执行类似于baz = new String(bar)的操作,编译器仍然可能知道它们是相同的东西。但主要的问题是当编译器看到文字字符串时,它可以轻松地优化相同的字符串。
我不知道它在运行时是如何工作的,但我认为JVM不会保留“活动字符串”的列表并检查是否存在相同的字符串。(例如,如果你两次读取输入行,并且用户两次输入相同的内容,则不会检查第二个输入字符串是否与第一个相同,并将它们指向相同的内存)。这将节省一些堆内存,但是这么微不足道的开销不值得。再次强调,文字字符串易于编译器进行优化。
以上就是关于“==”与“.equals()”以及它们看起来随机的原因的详细解释。

6

== 运算符是对值的简单比较。
对于对象引用,这些 (values) 是 (references)。因此,如果 x 和 y 引用同一个对象,则 x == y 返回 true。


4

在更高的帖子中,有人说“==”用于整数和检查空值。它也可以用于检查布尔运算和字符类型。

但一定要非常小心,并仔细检查您正在使用的是字符而不是字符串。例如:

    String strType = "a";
    char charType = 'a';

对于字符串,您可以进行如下检查:

这将是正确的。

    if(strType.equals("a")
        do something

但是
    if(charType.equals('a')
        do something else

“would be incorrect”这个表述不太准确,正确的做法是按照以下步骤操作。
    if(charType == 'a')
         do something else

4

a==b

比较引用,而不是值。在对象引用方面使用==通常限于以下情况:

  1. 比较以查看引用是否为null

  2. 比较两个枚举值。这是可行的,因为每个enum常量只有一个对象。

  3. 您想知道两个引用是否指向同一个对象

"a".equals("b")

比较值是否相等。由于这个方法是在Object类中定义的,从中派生出所有其他类,因此它对于每个类都自动定义。但是,除非该类覆盖它,否则它不会对大多数类执行智能比较。对于大多数Java核心类,它已被定义为有意义的方式。如果它未针对(用户)类定义,则其行为与==相同。


4

.equals()方法会检查两个字符串的值是否相等,并返回一个boolean值,而==运算符则会检查两个字符串是否是同一对象。


3
请使用Split而不是tokenizer,它肯定会提供给您精确的输出。 例如:
string name="Harry";
string salary="25000";
string namsal="Harry 25000";
string[] s=namsal.split(" ");
for(int i=0;i<s.length;i++)
{
System.out.println(s[i]);
}
if(s[0].equals("Harry"))
{
System.out.println("Task Complete");
}

这样一来,我相信你会得到更好的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接