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");
这里的abc
和xyz
,都是指相同的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");
这里abc
和xyz
是两个不同的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是否指向同一个对象)。 由于str1
和str2
在内存中引用的是相同的string,它们是相同的。 方法equals
检查两个对象是否相等(两个对象是否具有相同的内容)。 当然, str1
和str2
的内容是一样的。
当代码String str3 = new String("Hello world.")
执行一个新的string实例,其内容为"Hello world."
被创build,并且被variablesstr3
。 然后是内容为"Hello world."
另一个string实例"Hello world."
被再次创build,并由str4
。 由于str3
和str4
引用了两个不同的实例,它们并不相同,但其内容相同。
因此,输出包含四行:
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
比较引用,而不是值。 ==
与对象引用的使用通常仅限于以下内容:
-
比较一下引用是否为
null
。 -
比较两个枚举值。 这是有效的,因为每个
enum
常量只有一个对象。 -
你想知道两个引用是否是同一个对象
"a".equals("b")
比较相等的值。 因为这个方法是在Object
类中定义的,所有其他类都是从这个类派生的,所以它会自动为每个类定义。 但是,除非类重写它,否则它不会对大多数类进行智能比较。 对于大多数Java核心类,它已经被有意义地定义了。 如果它没有为(用户)类定义,则它的行为与==
相同。