Java的String.equals与==

这段代码将一个string分隔成一个标记,并将它们存储在一个string数组中,然后将一个variables与第一个房屋进行比较…为什么它不工作?

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)函数比较string,而不是==运算符。

函数检查string的实际内容, ==运算符检查对象的引用是否相等。 请注意,string常量通常是“interned”,使得两个具有相同值的常量实际上可以与==进行比较,但最好不要依赖于这个常量。

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

注意:比较是在'usuario'上完成的,因为在你的代码中保证了非空,尽pipe你仍然应该检查你是否确实在数组中有一些令牌,否则你会得到一个数组超出范围例外。

见约曼

约曼是一个成功的商人,有两间房子。

在这里输入图像描述

但其他人不知道。

这是同一个约曼吗?

当你问麦迪逊或伯克街道的邻居时,这是他们唯一可以说的:

在这里输入图像描述

单独使用住所,很难确认这是同一个Jorman。 由于它们是两个不同的地址,所以假设这两个不同的人是自然的。

这就是运算符==行为。 所以它会说, datos[0]==usuario是错误的,因为它只比较地址

调查人员的救援

如果我们派一名调查员呢? 我们知道这是同一个约曼,但我们需要certificate这一点。 我们的侦探将密切关注所有的物理方面。 经过深入的调查,代理人将能够得出是否是同一个人。 让我们看看它发生在Java术语。

这里是String的equals()方法的源代码:

在这里输入图像描述

它比较string字符,以得出他们确实是平等的结论。

这就是String equals方法的行为。 所以datos[0].equals(usuario)将返回true,因为它执行逻辑比较

注意在某些情况下,使用“==”运算符可能会导致预期的结果,因为java处理string的方式 – string文字在编译过程中被实现(参见String.intern() ) – 所以当您为例如"hello world"在两个类中,并将这些string与“==”进行比较,您可以得到结果:true,这是根据规范期望的; 当你比较相同的string(如果它们具有相同的值),当第一个是string文字(即通过"i am string literal"定义),第二个是在运行时期间构造。 与“新”关键字,如new String("i am string literal")== (相等)运算符返回false,因为他们都是不同的实例的String类。

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

更新 :01.04.2013我更新了这个post,由于下面的评论是正确的。 本来我声明interning(String.intern)是JVM优化的副作用。 虽然它确实节省了内存资源(这就是我所说的“优化”),但它主要是语言的特点

equals()函数是Object类的一个方法,应该被程序员覆盖。 String类重写它来检查两个string是否相等,即在内容中而不是引用。

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

考虑这些程序

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

这里的abcxyz ,都是指相同的String "Awesome" 。 因此expression式(abc == xyz)true

 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是两个不同的string,内容是"Hello World" 。 因此,这里的expression式(abc == xyz)false ,因为(abc.equals(xyz))true

希望您了解==<Object>.equals()之间的区别

谢谢。

代替

 datos[0] == usuario 

使用

 datos[0].equals(usuario) 

==比较variables的引用,其中.equals()比较你想要的值。

==testing引用相等。

.equals()testing值是否相等。

因此,如果你真的想testing两个string是否具有相同的值,你应该使用.equals() (除了在一些情况下,你可以保证两个具有相同值的string将被相同的对象表示,例如: String interning )。

==用于testing两个string是否是相同的Object

 // 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() (一个指针比较而不是一个循环)要便宜得多,因此,在适用的情况下(也就是说,你可以保证你只处理internedstring),它可以呈现出重要的性能提升。 但是,这些情况很less见。

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

请注意.equals()方法属于类对象(所有类的超级类)。 您需要根据您的类需求来覆盖它,但对于已经实现的string,它会检查两个string是否具有相同的值。

 Case1) String s1 = "StackOverflow"; String s2 = "StackOverflow"; s1 == s1; //true s1.equals(s2); //true Reason: String literals created without null are stores in String pool in permgen area of heap. So both s1 and s2 point to same object in the pool. Case2) String s1 = new String("StackOverflow"); String s2 = new String("StackOverflow"); s1 == s2; //false s1.equals(s2); //true Reason: If you create String object using new keyword separate space is allocated to it on heap. 

如果在将string插入数组之前调用intern() ,它也会起作用。 Internedstring是引用等于( == )当且仅当它们是值相等( equals()

 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,以了解string的身份和平等:

 public static void testEquality(){ String str1 = "Hello world."; String str2 = "Hello world."; if (str1 == str2) System.out.print("str1 == str2\n"); else System.out.print("str1 != str2\n"); if(str1.equals(str2)) System.out.print("str1 equals to str2\n"); else System.out.print("str1 doesn't equal to str2\n"); String str3 = new String("Hello world."); String str4 = new String("Hello world."); if (str3 == str4) System.out.print("str3 == str4\n"); else System.out.print("str3 != str4\n"); if(str3.equals(str4)) System.out.print("str3 equals to str4\n"); else System.out.print("str3 doesn't equal to str4\n"); } 

当第一行代码String str1 = "Hello world." 执行时,会创build一个string"Hello world." str2现有""Hello world."

operator ==检查两个对象的身份(两个variables是否指向同一个对象)。 由于str1str2在内存中引用的是相同的string,它们是相同的。 方法equals检查两个对象是否相等(两个对象是否具有相同的内容)。 当然, str1str2的内容是一样的。

当代码String str3 = new String("Hello world.")执行一个新的string实例,其内容为"Hello world." 被创build,并且被variablesstr3 。 然后是内容为"Hello world."另一个string实例"Hello world." 被再次创build,并由str4 。 由于str3str4引用了两个不同的实例,它们并不相同,但其内容相同。

因此,输出包含四行:

 Str1 == str2 Str1 equals str2 Str3! = str4 Str3 equals str4 

你应该使用stringequals来比较两个string是否相等,而不是运算符==,它只是比较引用。

==运算符比较java中对象的引用。 你可以使用string的equals方法。

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

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

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


技术解释

在Java中,所有variables都是原始types引用

(如果你需要知道一个引用是什么:“对象variables”只是指向对象的指针,所以用Object something = ... ,内存中的东西实际上就是一个地址(一个数字)。

==比较确切的值。 所以它比较了原始值是否相同,或者引用(地址)是否相同。 这就是为什么==往往不适用于string; string是对象,对两个stringvariables的处理==只是比较地址在内存中是否相同,正如其他人指出的那样。 .equals()调用对象的比较方法,它将比较引用指向的实际对象。 在string的情况下,它比较每个字符,看看它们是否相等。


有趣的部分

那么为什么==有时会为string返回true? 请注意,string是不可变的。 在你的代码中,如果你这样做

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

由于string是不可变的(当你调用.trim()或者其他东西时,它会产生一个新的string,而不是修改指向内存的原始对象),你并不需要两个不同的String("hi")对象。 如果编译器很聪明,那么字节码将被读取,只生成一个String("hi")对象。 所以,如果你这样做

 if (foo == bar) ... 

之后,他们指向相同的对象,并将返回true。 但是你很less打算这样做。 相反,你要求用户input,这是在内存的不同部分创build新的string等。

注意 :如果你做了像baz = new String(bar)那样的东西,编译器仍然可以看出它们是一样的。 但重点是当编译器看到文字string时,它可以很容易地优化相同的string。

我不知道它在运行时是如何工作的,但是我假设JVM没有保留“活动string”列表,并检查是否存在相同的string。 (例如,如果您读取两行input,并且用户input两次相同的input,则不会检查第二个inputstring是否与第一个inputstring相同,并将它们指向相同的内存)。 它会节省一点堆内存,但它是微不足道的开销是不值得的。 再说一次,编译器很容易优化文字string。

在那里,你有一个坚韧的解释==.equals() ,为什么它看起来是随机的。

@ 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 } } 

如果您要比较任何stringie)原始string的赋值,那么“==”和.equals都可以工作,但是对于新的string对象,只能使用.equals,这里“==”不起作用

例:

 String a = "name"; String b = "name"; 

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

 String a = new String("a"); 

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

所以最好使用.equals运算符….

.equals()将检查两个string是否具有相同的值,并返回boolean值,因为==运算符会检查两个string是否是相同的对象。

通常, .equals用于Object比较,在这里您要validation两个Objects是否具有相同的值。

==用于参考比较(两个Objects是堆上的同一Object )并检查Object是否为空。 它也被用来比较原始types的值。

使用分割而不是分词器,它将一定为你提供精确的输出:

 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"); } 

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

有人在上面的post中说==用于int和检查空值。 它也可以用来检查布尔操作和字符types。

要小心,仔细检查你使用的是字符而不是string。 例如

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

对于string,你会然后检查这将是正确的

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

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

将是不正确的,你需要做到以下几点

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

a==b

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

  1. 比较一下引用是否为null

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

  3. 你想知道两个引用是否是同一个对象

"a".equals("b")

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