java ==、equals和hashCode的区别和联系

基础类型

4种整数类型:int、long、byte、short

2种浮点数类型:float、double

1种字符类型:char

1种布尔类型:boolean

引用数据类型

接口

数组

1. ==

1.对于基本类型来说

==比较的是值是否相等

例如:



int a = 1;    
int b = 1;
System.out.println(a == b); true
double a = 1;
double b = 1;
System.out.println(a == b); true
int a = 1;
int b = 2;
System.out.println(a == b); false
double a = 1;
double b = 2;
System.out.println(a == b); false


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()方法被重写,则根据重写过程来比较














posted @ 2020-01-03 22:59  归去如风  阅读(175)  评论(0编辑  收藏  举报