java ==、equals和hashCode的区别和联系
基础类型
4种整数类型:int、long、byte、short
2种浮点数类型:float、double
1种字符类型:char
1种布尔类型:boolean
引用数据类型
类
接口
数组
1. ==
1.对于基本类型来说
==比较的是值是否相等
例如:
int a = 1; |
double a = 1; |
int a = 1; |
double a = 1; |
2.对于引用类型来说
== 比较的是两者在内存中存放的地址(堆内存地址)
获取地址可用:
System.identityHashCode(Object obj)
一个对象的identityHashCode能够始终和该对象的内部地址有一个相对应的关系,从这个角度来讲,它可以用于代表对象的引用地址
以下装箱不懂的可以看java装箱和拆箱内容,看完以后就会懂下面都意思。
Integer a = 1;
Integer b = 1;
System.out.println(System.identityHashCode(a)); == 22756955
System.out.println(System.identityHashCode(b)); == 22756955
System.out.println(a == b); true
a,b会自动装箱,执行了valueOf函数,它们的值在(-128,128]这个范围内 它们引用到了同一个Integer对象,所以它们肯定是相等的
Integer a = 200;
Integer b = 200;
System.out.println(System.identityHashCode(a)); == 22756955
System.out.println(System.identityHashCode(b)); == 1640639994
System.out.println(a == b); false
它们的值大于128,所以会执行new Integer(200),也就是说它们会分别创建两个不同的对象,所以它们肯定不等
Double a = 1.0;
Double b = 1.0;
System.out.println(System.identityHashCode(a)); == 22756955
System.out.println(System.identityHashCode(b)); == 1640639994
System.out.println(a == b); false
对于Double类型来说,我们就不能这样做,因为它在这个范围内个数是无限的
Boolean a = true;
Boolean b = true;
System.out.println(System.identityHashCode(a)); == 22756955
System.out.println(System.identityHashCode(b)); == 22756955
System.out.println(a == b); true
可以看到返回的都是true,也就是它们执行valueOf返回的都是相同的对象。并没有创建对象,因为在内部已经提前创建好两个对象,因为它只有两种情况,这样也是为了避免重复创建太多的对象
Integer a = 400;
int b = 400;
System.out.println(System.identityHashCode(a)); == 22756955
System.out.println(System.identityHashCode(b)); == 1640639994
System.out.println(a == b); true
是不是很神奇,地址不一样都相等,其实这是a进行了拆箱
a进行拆箱返回int,然后就是int和int进行比较,所以返回true
关于String,这是个特殊的引用类型以下讲解
String a = "1";
String b = "1";
System.out.println(System.identityHashCode(a)); == 22756955
System.out.println(System.identityHashCode(b)); == 22756955
System.out.println(a == b); true
引用同一个 String 对象
字符串缓冲池
String s1 = "Monday";
String s2 = new String("Monday");
s1 != s2
s1 equals s2
原来,程序在运行的时候会创建一个字符串缓冲池当使用 s2 = "Monday" 这样的表达是创建字符串的时候,程序首先会在这个String缓冲池中寻找相同值的对象,在第一个程序中,s1先被放到了池中,所以在s2被创建的时候,程序找到了具有相同值的 s1
将s2引用s1所引用的对象"Monday"
第二段程序中,使用了 new 操作符,他明白的告诉程序:"我要一个新的!不要旧的!"于是一个新的"Monday"Sting对象被创建在内存中。他们的值相同,但是位置不同,
2.equals
所有类都是继承于Object这个超类的,有一个equals()方法
这个方法很简单,就是比较对象的内存地址的。所以对象没有重写这个方法时,默认使用此方法,即比较对象的内存地址值。
下面来看下String类重写的方法:
可以看出,String的equals()方法仅仅是对比它的 数据值,而不是对象的内存地址,所以不管String对象的内存地址是否相同并不影响其结果,equals()比较的仅仅是数据值。
不只是String重写来equals,Double,Integer,Long....都重写了(去看源代码),所以都是比较数据值
Integer a = 1;
Integer b = 1;
System.out.println(System.identityHashCode(a));
System.out.println(System.identityHashCode(b));
System.out.println(a.equals(b)); true
总结
equals()和==的区别:
==
基本类型:对比它们的值是否相等
引用类型:对比它们的内存地址是否相等
equals()
引用类型:默认情况下,对比它们的地址是否相等;前提是要类型都相同,如果equals()方法被重写,则根据重写过程来比较