724

到目前为止,我一直==在我的程序中使用运算符来比较我的所有字符串。但是,我遇到了一个错误,将其中一个.equals()改为,它修复了这个错误。

==坏吗?什么时候应该使用,什么时候不应该使用?有什么不同?

4

23 回答 23

5882

==测试引用相等性(它们是否是同一个对象)。

.equals()测试值相等(它们在逻辑上是否“相等”)。

Objects.equals()null在调用之前检查,.equals()因此您不必这样做(从 JDK7 开始可用,在Guava中也可用)。

因此,如果您想测试两个字符串是否具有相同的值,您可能需要使用Objects.equals().

// These two have the same value
new String("test").equals("test") // --> true 

// ... but they are not the same object
new String("test") == "test" // --> false 

// ... neither are these
new String("test") == new String("test") // --> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" // --> true 

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

您几乎总是想使用Objects.equals(). 在您知道自己正在处理实习字符串的极少数情况下,您可以使用.==

JLS 3.10.5。字符串文字

此外,字符串字面量始终指代一个 class 实例String。这是因为字符串文字 - 或者更一般地说,作为常量表达式的值的字符串(第 15.28 节) - 是“内部的”,以便使用 方法共享唯一实例String.intern

类似的例子也可以在JLS 3.10.5-1中找到。

其他需要考虑的方法

String.equalsIgnoreCase()忽略大小写的值相等。但是请注意,此方法在各种与语言环境相关的情况下可能会产生意外结果,请参阅此问题

String.contentEquals()将 theString的内容与 any 的内容进行比较CharSequence(Java 1.5 起可用)。使您不必在进行相等比较之前将您的 StringBuffer 等转换为字符串,但将空值检查留给您。

于 2009-02-04T23:19:49.770 回答
758

==测试对象引用,.equals()测试字符串值。

有时看起来好像是在==比较值,因为 Java 做了一些幕后工作来确保相同的内联字符串实际上是同一个对象。

例如:

String fooString1 = new String("foo");
String fooString2 = new String("foo");

// Evaluates to false
fooString1 == fooString2;

// Evaluates to true
fooString1.equals(fooString2);

// Evaluates to true, because Java uses the same object
"bar" == "bar";

但要注意空值!

==处理null字符串很好,但从空字符串调用.equals()会导致异常:

String nullString1 = null;
String nullString2 = null;

// Evaluates to true
System.out.print(nullString1 == nullString2);

// Throws a NullPointerException
System.out.print(nullString1.equals(nullString2));

因此,如果您知道这fooString1可能为空,请告诉读者,通过编写

System.out.print(fooString1 != null && fooString1.equals("bar"));

以下内容更短,但它检查 null 的情况不太明显:

System.out.print("bar".equals(fooString1));  // "bar" is never null
System.out.print(Objects.equals(fooString1, "bar"));  // Java 7 required
于 2009-02-04T23:50:40.817 回答
467

==比较对象引用。

.equals()比较字符串值。

有时==会产生比较字符串值的错觉,例如以下情况:

String a="Test";
String b="Test";
if(a==b) ===> true

这是因为当您创建任何字符串字面量时,JVM 首先会在字符串池中搜索该字面量,如果找到匹配项,则会为新字符串提供相同的引用。正因为如此,我们得到:

(a==b) ===> 真

                       String Pool
     b -----------------> "test" <-----------------a

但是,==在以下情况下失败:

String a="test";
String b=new String("test");
if (a==b) ===> false

在这种情况下,new String("test")语句 new String 将在堆上创建,并且该引用将被提供给b,因此b将在堆上而不是在字符串池中提供引用。

现在a指向字符串池中的字符串,同时b指向堆上的字符串。因此我们得到:

如果(a==b)===> 错误。

                String Pool
     "test" <-------------------- a

                   Heap
     "test" <-------------------- b

虽然.equals()总是比较 String 的值,所以它在两种情况下都为真:

String a="Test";
String b="Test";
if(a.equals(b)) ===> true

String a="test";
String b=new String("test");
if(a.equals(b)) ===> true

所以使用.equals()总是更好。

于 2013-01-02T14:05:35.707 回答
229

==操作员检查两个字符串是否是完全相同的对象。

.equals()方法将检查两个字符串是否具有相同的值。

于 2009-02-04T23:21:25.540 回答
186

Java 中的字符串是不可变的。这意味着每当您尝试更改/修改字符串时,您都会获得一个新实例。您不能更改原始字符串。这样做是为了可以缓存这些字符串实例。一个典型的程序包含大量的字符串引用,缓存这些实例可以减少内存占用并提高程序的性能。

使用 == 运算符进行字符串比较时,您不是在比较字符串的内容,而是在实际比较内存地址。如果它们都相等,则返回 true ,否则返回 false 。而字符串中的equals比较字符串内容。

所以问题是如果所有字符串都缓存在系统中,为什么==返回false而equals返回true?嗯,这是可能的。如果您String str = new String("Testing")创建一个新字符串,即使缓存已经包含具有相同内容的字符串,您最终也会在缓存中创建一个新字符串。总之"MyString" == new String("MyString")总是会返回false。

Java 还讨论了函数 intern() 可用于字符串以使其成为缓存的一部分,因此"MyString" == new String("MyString").intern()将返回 true。

注意: == 运算符比 equals 快得多,因为您正在比较两个内存地址,但您需要确保代码没有在代码中创建新的 String 实例。否则你会遇到错误。

于 2009-02-05T10:54:17.493 回答
151
String a = new String("foo");
String b = new String("foo");
System.out.println(a == b); // prints false
System.out.println(a.equals(b)); // prints true

确保你明白为什么。这是因为==比较只比较参考;该equals()方法对内容进行逐个字符的比较。

当您为aand调用 new 时b,每个人都会获得一个指向"foo"字符串表中的新引用。参考文献不同,但内容相同。

于 2009-02-04T23:25:04.830 回答
129

是的,很糟糕……

==意味着您的两个字符串引用是完全相同的对象。您可能听说过这种情况,因为 Java 保留了某种文字表(它确实如此),但情况并非总是如此。一些字符串以不同的方式加载,由其他字符串构造等等,所以你绝不能假设两个相同的字符串存储在同一个位置。

Equals 为您进行真正的比较。

于 2009-02-04T23:20:18.647 回答
126

是的,==不利于比较字符串(实际上是任何对象,除非您知道它们是规范的)。 ==只是比较对象引用。 .equals()测试平等。对于字符串,它们通常是相同的,但正如您所发现的,这并不总是得到保证。

于 2009-02-04T23:19:49.940 回答
122

Java 有一个字符串池,Java 在该池下管理字符串对象的内存分配。请参阅Java 中的字符串池

当您使用==运算符检查(比较)两个对象时,它会将地址相等性与字符串池进行比较。如果两个 String 对象具有相同的地址引用,则返回true,否则返回false。但是如果要比较两个 String 对象的内容,则必须重写该equals方法。

equals实际上是 Object 类的方法,但它被重写到 String 类中,并给出了一个新的定义,它比较了 object 的内容。

Example:
    stringObjectOne.equals(stringObjectTwo);

但请注意它尊重字符串的情况。如果您想要不区分大小写的比较,那么您必须使用 String 类的 equalsIgnoreCase 方法。

让我们来看看:

String one   = "HELLO"; 
String two   = "HELLO"; 
String three = new String("HELLO"); 
String four  = "hello"; 

one == two;   // TRUE
one == three; // FALSE
one == four;  // FALSE

one.equals(two);            // TRUE
one.equals(three);          // TRUE
one.equals(four);           // FALSE
one.equalsIgnoreCase(four); // TRUE
于 2013-04-02T09:15:33.830 回答
105

我同意zacherates的回答。

但是你可以做的是调用intern()你的非文字字符串。

从 zacherates 示例:

// ... but they are not the same object
new String("test") == "test" ==> false 

如果您实习非文字字符串相等是true

new String("test").intern() == "test" ==> true 
于 2009-02-05T08:14:48.927 回答
103

==比较 Java中的对象引用,对象也不例外String

为了比较对象(包括String)的实际内容,必须使用equals方法

如果两个String对象的比较==结果是true,那是因为String对象是被实习的,并且 Java 虚拟机有多个引用指向 的同一个实例String。不应期望将String包含相同内容的一个对象与另一个String对象进行比较==,以评估为true

于 2009-02-04T23:20:08.413 回答
101

.equals()比较一个类中的数据(假设函数已实现)。 ==比较指针位置(对象在内存中的位置)。

==如果两个对象(NOT TALKING ABOUT PRIMITIVES)都指向同一个对象实例,则返回 true。 .equals()如果两个对象包含相同的数据,则返回 true equals()Versus ==in Java

这可能会帮助你。

于 2009-02-04T23:20:47.273 回答
100

==执行引用相等检查,这 2 个对象(在本例中为字符串)是否引用内存中的同一对象。

equals()方法将检查2 个对象的内容状态是否相同。

显然==更快,但是如果您只想判断 2 Strings 是否包含相同的文本,在许多情况下会(可能)给出错误的结果。

绝对推荐使用该equals()方法。

不用担心性能。鼓励使用的一些事情String.equals()

  1. 执行String.equals()第一次检查引用相等性(使用==),如果两个字符串通过引用相同,则不执行进一步计算!
  2. 如果 2 个字符串引用不相同,String.equals()接下来将检查字符串的长度。这也是一个快速的操作,因为String该类存储了字符串的长度,无需计算字符或代码点。如果长度不同,则不执行进一步检查,我们知道它们不可能相等。
  3. 只有当我们走到这一步时,才会真正比较两个字符串的内容,这将是一个速记比较:如果我们发现一个不匹配的字符(在两个字符串中的相同位置),并不是所有的字符都会被比较),将不再检查其他字符。

总而言之,即使我们保证字符串是实习生,使用该equals()方法仍然不是人们可能认为的那样开销,绝对是推荐的方式。如果您想要一个有效的引用检查,那么在语言规范和实现保证相同的枚举值将是相同的对象(通过引用)的情况下使用枚举。

于 2013-03-28T12:22:37.447 回答
83

如果您像我一样,当我第一次开始使用 Java 时,我想使用“==”运算符来测试两个 String 实例是否相等,但无论好坏,这在 Java 中都不是正确的方法。

在本教程中,我将演示几种正确比较 Java 字符串的不同方法,从我大部分时间使用的方法开始。在本 Java 字符串比较教程的最后,我还将讨论为什么“==”运算符在比较 Java 字符串时不起作用。

选项 1:Java String 与 equals 方法比较 大多数时候(可能是 95% 的时间)我用 Java String 类的 equals 方法比较字符串,如下所示:

if (string1.equals(string2))

此 String equals 方法查看两个 Java 字符串,如果它们包含完全相同的字符串,则认为它们相等。

看一个使用 equals 方法的快速字符串比较示例,如果运行以下测试,两个字符串将不会被视为相等,因为字符不完全相同(字符的大小写不同):

String string1 = "foo";
String string2 = "FOO";

if (string1.equals(string2))
{
    // this line will not print because the
    // java string equals method returns false:
    System.out.println("The two strings are the same.")
}

但是,当两个字符串包含完全相同的字符串时,equals 方法将返回 true,如下例所示:

String string1 = "foo";
String string2 = "foo";

// test for equality with the java string equals method
if (string1.equals(string2))
{
    // this line WILL print
    System.out.println("The two strings are the same.")
}

选项 2:使用 equalsIgnoreCase 方法进行字符串比较

在某些字符串比较测试中,您需要忽略字符串是大写还是小写。当您想以这种不区分大小写的方式测试字符串是否相等时,请使用 String 类的 equalsIgnoreCase 方法,如下所示:

String string1 = "foo";
String string2 = "FOO";

 // java string compare while ignoring case
 if (string1.equalsIgnoreCase(string2))
 {
     // this line WILL print
     System.out.println("Ignoring case, the two strings are the same.")
 }

选项 3:使用 compareTo 方法比较 Java 字符串

还有第三种比较不常用的方法来比较 Java 字符串,那就是使用 String 类的 compareTo 方法。如果两个字符串完全相同,则 compareTo 方法将返回值 0(零)。下面是这个字符串比较方法的简单示例:

String string1 = "foo bar";
String string2 = "foo bar";

// java string compare example
if (string1.compareTo(string2) == 0)
{
    // this line WILL print
    System.out.println("The two strings are the same.")
}

当我在写 Java 中的这个相等概念时,重要的是要注意 Java 语言在基本 Java Object 类中包含一个 equals 方法。每当您创建自己的对象并且想要提供一种方法来查看对象的两个实例是否“相等”时,您应该在您的类中覆盖(并实现)这个 equals 方法(以 Java 语言提供的相同方式String equals 方法中的这种相等/比较行为)。

您可能想看看这个==、.equals()、compareTo() 和 compare()

于 2013-06-11T09:17:11.060 回答
78

功能:

public float simpleSimilarity(String u, String v) {
    String[] a = u.split(" ");
    String[] b = v.split(" ");

    long correct = 0;
    int minLen = Math.min(a.length, b.length);

    for (int i = 0; i < minLen; i++) {
        String aa = a[i];
        String bb = b[i];
        int minWordLength = Math.min(aa.length(), bb.length());

        for (int j = 0; j < minWordLength; j++) {
            if (aa.charAt(j) == bb.charAt(j)) {
                correct++;
            }
        }
    }

    return (float) (((double) correct) / Math.max(u.length(), v.length()));
}

测试:

String a = "This is the first string.";

String b = "this is not 1st string!";

// for exact string comparison, use .equals

boolean exact = a.equals(b);

// For similarity check, there are libraries for this
// Here I'll try a simple example I wrote

float similarity = simple_similarity(a,b);
于 2013-03-24T14:01:20.520 回答
78

==操作员检查两个引用是否指向同一个对象。.equals()检查实际的字符串内容(值)。

注意该.equals()方法属于类Object(所有类的超类)。您需要根据您的类要求覆盖它,但对于 String 它已经实现,它会检查两个字符串是否具有相同的值。

  • 情况1

    String s1 = "Stack Overflow";
    String s2 = "Stack Overflow";
    s1 == s2;      //true
    s1.equals(s2); //true
    

    原因:创建的不带 null 的字符串字面量存储在堆的 permgen 区域的字符串池中。所以 s1 和 s2 都指向池中的同一个对象。

  • 案例2

    String s1 = new String("Stack Overflow");
    String s2 = new String("Stack Overflow");
    s1 == s2;      //false
    s1.equals(s2); //true
    

    原因:如果您使用关键字创建 String 对象new,则会在堆上为其分配一个单独的空间。

于 2013-07-25T05:08:18.870 回答
54

==比较对象的引用值,而类equals()中的方法java.lang.String比较对象的内容String(与另一个对象)。

于 2012-04-12T05:25:59.517 回答
51

我认为,当您定义 a 时,您就定义了String一个对象。所以你需要使用.equals(). 当您使用原始数据类型时,您必须使用(和任何对象)==String必须使用.equals().

于 2013-01-08T04:37:14.720 回答
49

如果该equals()方法存在于java.lang.Object类中,并且需要检查对象状态的等价性!这意味着,对象的内容。而==操作员需要检查实际的对象实例是否相同。

例子

考虑两个不同的参考变量,str1str2

str1 = new String("abc");
str2 = new String("abc");

如果您使用equals()

System.out.println((str1.equals(str2))?"TRUE":"FALSE");

您将获得输出,TRUE就像您使用==.

System.out.println((str1==str2) ? "TRUE" : "FALSE");

现在您将获得FALSEas 输出,因为两者str1str2都指向两个不同的对象,即使它们共享相同的字符串内容。这是因为new String()每次都会创建一个新对象。

于 2013-12-18T19:26:34.653 回答
45

运算符==始终用于对象引用比较,而 String 类.equals()方法被覆盖以进行内容比较

String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1 == s2); // It prints false (reference comparison)
System.out.println(s1.equals(s2)); // It prints true (content comparison)
于 2013-04-30T06:14:22.447 回答
40

所有对象都保证有一个.equals()方法,因为 Object 包含一个方法,.equals(),它返回一个布尔值。如果需要进一步定义,则覆盖此方法是子类的工作。如果没有它(即使用==),则只会检查两个对象之间的内存地址是否相等。String 覆盖此.equals()方法,它不使用内存地址,而是返回字符级别的字符串比较是否相等。

一个重要的注意事项是字符串存储在一个集中池中,因此一旦创建了字符串,它就会永远存储在同一地址的程序中。字符串不会改变,它们是不可变的。这就是为什么如果您有大量的字符串处理要做,那么使用常规字符串连接是一个坏主意。相反,您将使用StringBuilder提供的类。请记住,指向该字符串的指针可以更改,如果您有兴趣查看两个指针是否相同,那==将是一个不错的选择。字符串本身没有。

于 2012-09-03T04:55:32.520 回答
39

您还可以使用该compareTo()方法比较两个字符串。如果 compareTo 结果为 0,则两个字符串相等,否则被比较的字符串不相等。

比较==引用而不比较实际字符串。如果您确实使用new String(somestring).intern()then 创建了每个字符串,则可以使用==运算符比较两个字符串,否则只能使用 equals() 或 compareTo 方法。

于 2013-05-29T02:51:02.743 回答
39

在 Java 中,当==运算符用于比较 2 个对象时,它会检查对象是否引用内存中的同一位置。换句话说,它检查这两个对象名称是否基本上是对同一内存位置的引用。

JavaString类实际上覆盖了类中的默认equals()实现Object——它覆盖了方法,因此它只检查字符串的值,而不是它们在内存中的位置。这意味着如果您调用该equals()方法来比较 2 个String对象,那么只要实际的字符序列相等,两个对象就被认为是相等的。

==操作员检查两个字符串是否是完全相同的对象。

.equals()方法检查两个字符串是否具有相同的值。

于 2014-01-14T11:07:15.467 回答