1. == 运算符
"==" 运算符用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量(例如:String s = new String() )是否相等,只能使用 "==" 运算符。
基本数据类型:int,short,long,boolean,char,float,double,byte
引用变量:·
String s = new String();
变量s占用了一块储存空间,而new String() 则存储在另外一块存储空间里(这里涉及到了两块内存),此时,变量s所对应的内存中的存储的数值就是对象占用的那块内存的首地址。
对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,那么要看这两个变量所对应的内存中的数值是否相等(这两个对象是否指向同一块存储空间,这时候就可以用"=="运算符进行比较。但是,如果要比较的是两个对象的内容是否相等,那么用"=="运算符就无法实现)。
那么问题来了,"=="运算符不能比较对象的内容,那要用什么呢?
我们先来看看equals的概念
2.equals
equals是Object类提供的方法之一,因为每一个Java类都继承自Object类,所以每一个对象都具有equals这个方法。因为Object类中定义的equals(Object)方法是直接使用"=="运算符比较的两个对象, 所以在没有覆盖equals(Object) 方法的情况下, equals(Object) 与“==”运算符一样,比较的是引用。
String s1 = new String("Hello");
String s2 = new String("Hello");
从代码输出结果结合上面的概念就比较容易理解:
== 返回false是因为 ==比较的是字符串的内存地址(引用)
equals返回false是因为 equals比较的是字符串的内容(值)
注:
这里可能有人会有疑惑为什么 equals 为什么不是返回false啊?不是说没有覆盖equals(Object) 方法的情况下, equals(Object) 与“==”运算符一样,比较的是引用吗?
那是因为Sun的API已经为String类重载了equals方法了,所以实际上已经被覆盖了。
下面的代码就是equals没有被覆盖的结果
public class Test {
private int batch;
public Test(int batch) {
this.batch = batch;
}
public static void main(String[] args) {
Test c1 = new Test(1);
Test c2 = new Test(1);
System.out.println(c1.equals(c2));
System.out.println(c1 == c2);
}
}
可以看到两个结果都是false,但是equlas也是false的原因是因为equlas没有被重载,没被重载的话实际上和 == 是一个作用。
3.hashCode方法
hashCode()方法是从Object类中继承过来的,也用来鉴定两个对象是否相等。Object类中的haseCode()方法返回对象在内存中地址转换成一个int值,所以如果没有重写hashCode()方法,那么任何对象的hashCode方法都是不相等的。
一般来说比较少用hashCode()来判断,因为它返回的是一个int值,相比其他两个没有这么直观。
4.== 和 equals使用对比
== 和 equals 两个方法都可以用来比较字符串,但是 == 要慎重使用(实际上就是不要用==来比较字符串,因为有可能会出现bug,而且可能是间歇性的出现),因为两个相同的字符串用 == 来比较也是会出现 false的现象。用代码来验证这个问题。
String a = "abcd";
String b = "ab";
String c = "cd";
String e = b + c;
String f = "abcdef";
String g = f.substring(0,4);
System.out.println("abcd".equals(a));
System.out.println("abcd".equals(e));
System.out.println("abcd".equals(g));
System.out.println();
System.out.println("abcd" == a);
System.out.println("abcd" == e);
System.out.println("abcd" == g);
注:a 是完整的“abcd” , e是通过 + 来拼接成“abcd” , g是通过substring字符串截取成“abcd”
1. 首先我们从equals 来看,可以看到三个对比都是true
2. 再来看 == ,第二、三个比较都是false,可以得出结论通过 +号拼接 和 substring截取 是不能用 == 来比较的。
结论
equals比较的是字符串的内容(值),因为上面4个字符串的内容都是 abcd ,所以返回的结果也都是true。
而 == 比较的是字符串的内存地址(引用),这里通过 +号拼接 和 substring截取 的两种方式改变了字符串的内存地址,理所当然,返回的结果就变为false。
也可以用这种方式来记忆,虚拟机始终将相同的字符串共享,就可以使用 == 运算符来检测是否相等。但是 +号拼接 和 substring截取 返回的结果并不是共享的。所以在程序中尽量不使用 == 来比较字符串。(使用==来比较字符串容易出现随机的、间歇性的bug)
附上一个比较字符串(不区分大小写)方法: equalsIgnoreCase