- 凡是比较基本类型(byte,short,int,long,char,float,double,boolean)
只能用==;比较结果你看到的字面值相等就会相等。
- 凡是比较引用类型(对象)
==比较的是两个引用是不是指向同一个内存地址;equals比较的是两个引用的字面值是不是相同;基本类型的包装类型是对象(引用)类型,所以除非两个相同字面值的引用指向同一内存地址,值才会相等,比如:
Integer a=new Integer(3);
Integer b=a; //互相赋值
这样用等号或equals比较都会得出true,记住一点,凡是两个引用都用了new去初始化,那==比较的结果都只会是false,互相之间有了赋值,比较结果就为true。
- 特别的——字符串常量池:
String a="abc";
String b="abc";
a==b和a.equals(b);结果都会为true,因为没有用new去新建对象,其实a和b都指向的是同一个String对象"abc",改成:
String a=new String("abc");
String b=new String"abc");
后==的结果就是false了。
- equals()和==的源码定义
public boolean equals(Object obj) {
return (this == obj);
}
可以看出equals与==是等效的(Object类中的equals没什么区别),不同的原因就在于有些类(像String、Integer等类)对equals进行了重写。
没有对equals进行重写的类就只能从Object类中继承equals方法,其equals方法与==就也是等效的。
- 对 == 进一步说明
== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指向同一个对象,比较的是真正意义上的指针操作。
1、比较的是操作符两端的操作数是否是同一个对象。
2、两边的操作数必须是同一类型的(可以是父子类之间)才能编译通过。
3、比较的是地址,如果是具体的阿拉伯数字的比较,值相等则为true,如:
int a=10 与 long b=10L 与 double c=10.0都是相同的(为true),因为他们都指向地址为10的堆。
- 对equals重写需要注意五点
1、自反性:对任意引用值X,x.equals(x)的返回值一定为true;
2、对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true;
3、传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true ;
4、 一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变;
5、非空性:任何非空的引用值X,x.equals(null)的返回值一定为false 。
- equals进一步说明
String s="abce"是一种非常特殊的形式,和new 有本质的区别,它是java中唯一不需要new 就可以产生对象的途径。
以String s="abce";形式赋值在java中叫直接量,它是在常量池中而不是象new一样放在压缩堆中。这种形式的字符串,在JVM内部发生字符串拘留,即当声明这样的一个字符串后,JVM会在常量池中先查找有有没有一个值为"abcd"的对象。
如果有,就会把它赋给当前引用.即原来那个引用和现在这个引用指点向了同一对象,如果没有,则在常量池中新创建一个“abcd"”,下一次如果有Strings1="abcd";又会将s1指向“abcd”这个对象,即以这形式声明的字符串,只要值相等,任何多个引用都指向同一对象。
而String s=new String("abcd”);和其它任何对象一样,每调用一次就产生一个对象,只要它们调用。
也可以这么理解:String str="hello”;先在内存中找是不是有“hello”这个对象,如果有,就让str指向那个“hello”。
如果内存里没有"hello",就创建一个新的对象保存"hello”。String str=new String(“hello")就是不管内存里是否已经有"hello"这个对象,都新建一个对象保存"hello"。