关于java:String.equals与==

String.equals versus ==

本问题已经有最佳答案,请猛点这里访问。

此代码将一个字符串分隔成标记,并将它们存储在一个字符串数组中,然后将变量与第一个主变量进行比较…为什么不起作用?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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");
    }
}


使用string.equals(Object other)函数比较字符串,而不是==运算符。

函数检查字符串的实际内容,==运算符检查对对象的引用是否相等。注意,字符串常量通常是"internet"的,这样两个具有相同值的常量实际上可以与==进行比较,但最好不要依赖它。

1
2
3
if (usuario.equals(datos[0])) {
    ...
}

注意:比较是在"usuario"上完成的,因为在代码中保证不为空,尽管您仍然应该检查在datos数组中是否确实有一些标记,否则您将得到一个超出界限的数组异常。


认识乔曼

乔曼是一个成功的商人,有两栋房子。

enter image description here

但其他人不知道。

是同一个乔曼吗?

当你问麦迪逊街或伯克街的邻居时,他们唯一能说的就是:

氧化镁

单独使用住所,很难确认这是同一个乔曼。因为他们是两个不同的地址,所以很自然地假设他们是两个不同的人。

这就是操作员==的行为方式。所以说datos[0]==usuario是假的,因为它只比较地址。

救援的调查员

如果我们派了一个调查员怎么办?我们知道这是同一个乔曼,但我们需要证明这一点。我们的侦探会仔细观察身体的各个方面。经过彻底的调查,代理人将能够断定是否是同一个人。让我们看看它发生在Java术语。

下面是string的equals()方法的源代码:

氧化镁

它逐字比较字符串,以得出它们确实相等的结论。

这就是字符串equals方法的行为方式。因此,datos[0].equals(usuario)将返回true,因为它执行逻辑比较。


值得注意的是,在某些情况下,使用"=="运算符可以得到预期的结果,因为在编译过程中如何处理Java字符串-字符串文本(参见EDCOX1 OR 7)。因此,当您在两个类中编写EDCOX1 OR 8表示,并将这些字符串与"=="比较时,可以得到结果:true,这是预期的。根据规范,当您比较相同的字符串(如果它们具有相同的值)时,第一个字符串是字符串文字(即通过"i am string literal"定义的),第二个字符串是在运行时构建的,即使用"new"关键字(如new String("i am string literal"))时,==运算符返回false,因为它们都是edo的不同实例CX1〔12〕类。

唯一正确的方法是使用.equals()->datos[0].equals(usuario)==只表示两个对象是同一个对象实例(即具有相同的内存地址)。

更新:2013年4月1日我更新了这篇文章,下面的评论是正确的。最初我声明interning(string.intern)是JVM优化的副作用。虽然它确实节省了内存资源(这就是我所说的"优化"),但它主要是语言的特性。


equals()函数是Object类的一种方法,应被程序员重写。String类重写它,以检查两个字符串是否相等,即在内容和非引用中。

==操作符检查两个对象的引用是否相同。

考虑程序

1
2
3
4
5
String abc ="Awesome" ;
String xyz =  abc;

if(abc == xyz)
     System.out.println("Refers to same string");

这里的abcxyz都指同一个String"Awesome"。因此,表达(abc == xyz)true

1
2
3
4
5
6
7
8
9
10
11
12
String abc ="Hello World";
String xyz ="Hello World";

if(abc == xyz)
    System.out.println("Refers to same string");
else
    System.out.println("Refers to different strings");

if(abc.equals(xyz))
     System.out.prinln("Contents of both strings are same");
else
     System.out.prinln("Contents of strings are different");

这里,abcxyz是两个不同的字符串,内容相同,"hello world"。因此,这里的表达式(abc == xyz)false,其中(abc.equals(xyz))true

希望你能理解==.equals()的区别。

谢谢。


而不是

1
datos[0] == usuario

使用

1
datos[0].equals(usuario)

==比较变量的引用,其中.equals()比较所需的值。


==参考等式检验。

.equals()检验值是否相等。

因此,如果您实际想要测试两个字符串是否具有相同的值,则应使用.equals()(除了可以保证具有相同值的两个字符串将由同一对象表示的少数情况,例如:Stringinterning)。

==用于测试两个字符串是否相同Object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 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

// concatenation of string literals happens at compile time resulting in same objects
"test" =="te" +"st"  ==> true

// but .substring() is invoked at runtime, generating distinct objects
"test" =="!test".substring(1) ==> false

需要注意的是,==equals()便宜得多(单指针比较而不是循环),因此,在适用的情况下(即,您可以保证只处理内部字符串),它可以带来重要的性能改进。然而,这些情况很少见。


1
2
The == operator checks if the two references point to the same object or not.
.equals() checks for the actual string content (value).

注意,.equals()方法属于类对象(所有类的超级类)。您需要根据类需求重写它,但是对于字符串,它已经实现,并且它检查两个字符串是否具有相同的值。

1
2
3
4
5
6
7
8
9
10
11
12
Case1)
String s1 ="Stack Overflow";
String s2 ="Stack Overflow";
s1 == s1;      // true
s1.equals(s2); // true
Reason: String literals created without null are stored in the string pool in the permgen area of the heap. So both s1 and s2 point to the same object in the pool.
Case2)
String s1 = new String("Stack Overflow");
String s2 = new String("Stack Overflow");
s1 == s2;      // false
s1.equals(s2); // true
Reason: If you create a String object using the `new` keyword a separate space is allocated to it on the heap.


如果在将字符串插入数组之前对其调用intern(),它也会工作。如果且仅当其值相等(equals()时,中间字符串才是引用相等(==)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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.intern();            
    i++;
}

//System.out.println (usuario);

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


让我们分析下面的Java,了解字符串的身份和相等性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public static void testEquality(){
    String str1 ="Hello world.";
    String str2 ="Hello world.";

    if (str1 == str2)
        System.out.print("str1 == str2
"
);
    else
        System.out.print("str1 != str2
"
);

    if(str1.equals(str2))
        System.out.print("str1 equals to str2
"
);
    else
        System.out.print("str1 doesn't equal to str2
"
);

    String str3 = new String("Hello world.");
    String str4 = new String("Hello world.");

    if (str3 == str4)
        System.out.print("str3 == str4
"
);
    else
        System.out.print("str3 != str4
"
);

    if(str3.equals(str4))
        System.out.print("str3 equals to str4
"
);
    else
        System.out.print("str3 doesn't equal to str4
"
);
}

当第一行代码String str1 ="Hello world."执行时,一个字符串\Hello world."。创建,变量str1引用它。由于优化,当下一行代码执行时,将不再创建另一个字符串"Hello world."。变量str2也指现有的""Hello world."

运算符==检查两个对象的标识(两个变量是否引用同一个对象)。由于str1str2在内存中指的是相同的字符串,所以它们是相同的。方法equals检查两个对象的相等性(两个对象是否具有相同的内容)。当然,str1str2的内容是相同的。

代码String str3 = new String("Hello world.")执行时,创建内容为"Hello world."的字符串的新实例,并由变量str3引用。然后再次创建内容为"Hello world."的字符串的另一个实例,并由埃多克斯1〔16〕。由于str3str4指的是两种不同的情况,它们并不相同,但它们内容相同。

因此,输出包含四行:

1
2
3
4
5
6
7
Str1 == str2

Str1 equals str2

Str3! = str4

Str3 equals str4


应该使用string equals来比较两个字符串是否相等,而不是运算符==来比较引用。


EDCOX1·6×操作符比较Java中对象的引用。您可以使用字符串的equals方法。

1
2
3
4
5
String s ="Test";
if(s.equals("Test"))
{
    System.out.println("Equal");
}

一般情况下,.equals用于Object比较,在这里您要验证两个Objects是否具有相同的值。

用于参考比较的==(两个Objects在堆上是同一个Object)和检查Object是否为空。它还用于比较基本类型的值。


如果要比较字符串的任何赋值,即基元字符串,则"=="和.equals都有效,但对于新的字符串对象,只应使用.equals,此处"=="将无效。

例子:

1
2
3
String a ="name";

String b ="name";

if(a == b)(a.equals(b))将返回真值。

但是

1
String a = new String("a");

在这种情况下,if(a == b)将返回false

所以最好使用.equals操作符…


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


@Melkhiah66可以使用Equals方法而不是"=="方法来检查相等性。如果使用intern(),则它检查对象是否在池中如果存在,则返回相等或不相等。Equals方法在内部使用哈希代码并获取所需的结果。埃多克斯1〔33〕


我知道这是一个古老的问题,但下面是我如何看待它(我觉得非常有用):

技术说明

在Java中,所有变量都是基元类型或引用。

(如果需要知道引用是什么,"对象变量"只是指向对象的指针。所以对于Object something = ...,有些东西实际上是内存中的一个地址(一个数字)。

==比较精确值。因此,它比较原始值是否相同,或者引用(地址)是否相同。这就是为什么==通常不适用于字符串;字符串是对象,对两个字符串变量执行==只是比较地址在内存中是否相同,如其他人指出的那样。.equals()调用对象的比较方法,比较引用指向的实际对象。在字符串的情况下,它比较每个字符,看它们是否相等。

有趣的部分:

那么,为什么==有时对字符串返回true?注意,字符串是不可变的。在你的代码中,如果你这样做的话

1
2
String foo ="hi";
String bar ="hi";

因为字符串是不可变的(当您调用.trim()或其他东西时,它会生成一个新的字符串,而不是修改内存中指向的原始对象),所以您实际上不需要两个不同的String("hi")对象。如果编译器是智能的,那么字节码将被读取以只生成一个String("hi")对象。所以如果你这样做的话

1
if (foo == bar) ...

紧接着,它们指向同一个对象,并将返回true。但你很少打算这么做。相反,您需要的是用户输入,它在内存的不同部分创建新的字符串,等等。

注意:如果您执行类似于baz = new String(bar)的操作,编译器可能仍然会发现它们是相同的。但主要的一点是,当编译器看到文本字符串时,它可以轻松地优化相同的字符串。

我不知道它在运行时是如何工作的,但是我假设JVM不保存"活动字符串"列表,并且检查是否存在相同的字符串。(例如,如果您读取一行输入两次,而用户输入相同的输入两次,则不会检查第二个输入字符串是否与第一个输入字符串相同,并将它们指向相同的内存)。它可以节省一点堆内存,但是开销是如此微不足道,不值得这样做。同样,关键是编译器很容易优化文本字符串。

给你了……一个关于==.equals()的粗糙解释,以及为什么它看起来是随机的。


埃多克斯1〔8〕

比较引用,而不是值。在对象引用中使用==通常仅限于以下内容:

  • 比较以查看引用是否为null

  • 比较两个枚举值。这是因为每个enum常量只有一个对象。

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

  • 埃多克斯1〔12〕

    比较值是否相等。因为此方法是在Object类中定义的,从该类派生所有其他类,所以它会自动为每个类定义。但是,除非类重写它,否则它不会对大多数类执行智能比较。它以一种有意义的方式被定义为大多数Java核心类。如果没有为(用户)类定义,它的行为与==相同。


    .equals()将检查两个字符串是否具有相同的值,并返回boolean值,其中,==运算符检查两个字符串是否为同一对象。


    有人在高一点的帖子上说,==用于int和检查空值。它还可以用于检查布尔操作和字符类型。

    但是要非常小心,并再次检查您使用的是字符而不是字符串。例如

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

    然后检查字符串这是对的

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

    但是

    1
    2
        if(charType.equals('a')
            do something else

    可能不正确,您需要执行以下操作

    1
    2
        if(charType == 'a')
             do something else


    使用split而不是tokenizer,它肯定会提供精确的输出例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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");
    }

    在这之后,我相信你会得到更好的结果……