1). 对于==,比较的是值是否相等
如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
如果作用于引用类型的变量,则比较的是所指向的对象的地址
2). 对于equals方法,注意:equals方法不能作用于基本数据类型的变量,equals继承Object类,比较的是是否是同一个对象
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容
举个例子来看:
String s1 = "cmy";
String s2 = "cmy";
System.out.println(s1 == s2); //true
System.out.println(s1.equals(s2));// true
s1和s2都指向常量池中cmy这个字符串。所以s1 == s2。
String重写了equals方法,所以比较的是所指向对象的内容。
String str1 = new String("cmy");
String str2 = new String("cmy");
System.out.println(str1 == str2); //false
System.out.println(str1.equals(str2)); //true
str1和str2是各自new了一个对象,自然地址是不一样的。
所以str1 == str2为false。
下面再看一下用final来修饰:
String a = "moon2";
final String b = "moon";
String d = "moon";
String c = b + 2;
String e = d + 2;
System.out.println("b == d:" + (b == d)); //true
System.out.println("a == c:" + (a == c)); //true
System.out.println("a == e:" + (a == e)); //false
System.out.println("-----------");
System.out.println("a.equals(c):" + a.equals(c)); //true
System.out.println("a.equals(e):" + a.equals(e)); //true
/**
* 解释一波:
* 1. 变量a指的是字符串常量池中的moon2;
* 2. 变量b是final修饰的,变量b的值在编译的时候就已经确定了它的确定值
* 换句话说就是提前知道了变量b的内容更到底是个啥,相当于是一个编译期常量。
* 3. 变量c是b+2 得到的,由于b是一个常量,所以在使用的时候直接相当于使用b的原始值(moon)
* 来进行计算,所以c生成的也是一个常量,a是常量,c也是常量,都是moon2,
* 而Java常量池中只生成一个唯一的moon2字符串,所以说a和c是相等的。
* 4. d是指向常量池中moon,但是d不是final修饰的,也就是说在使用d的时候不会提前知道d的
* 值是什么,所以在计算e的时候就不一样了,e的话由于使用的是d的引用计算,变量d的访问却需要在运行
* 时通过链接来进行,所以这种计算会在堆上生成moon2,所以e指向的是堆上的moon2。
* 就可得出a和e不相等。
*
* 总得来讲,a.c是常量池的moon2,e是堆上的moon2。
*/
注意:e所处的内存位置。