Java中equals()、==、hashCode()理解!

分析:要先了解==,hashCode()这两个内容,equals()中两者会涉及到。

1."=="运算符

= =是"相等",但分为两种情况:
引用类型:比较的是对象的内存地址是否相同。
Object obj=new Object();
Object ccc=new Object();
obj == ccc //false
基本类型:比较的是,因为基础类型变量是直接存放值在栈中的。
int a=100; int b=100;
a==b //true

2.hashCode()方法

hashCode()方法是用来返回对象的散列值的,是Object类的一个方法,具体概念这里就不说了,Google.
java有个规范:两个对象如果equals()返回值为true,这两个对象的散列值应该相等。

3.equals()方法

equals()方法是Object类的方法,基本类型变量是没有equals()方法的!!

	官方文档上描述equals()有五个特点:
	1.自反性:对象a.equals(a)返回值永远都为true;
	2.对称性:即有两对象a,b;   a.equals(b)和b.equals(a)返回值是一样的;
	3.传递性:有对象a,b,c;   a.equals(b)为true,a.equals(c)为true,则b.equals(c)为true;
	4.一致性:即多次调用equals方法,结果不变,a.equals(b)==a.equals(b);
	5.对于null:所有不为null的对象a,  a.equals(null)结果都为false; (null.equals(null)会报空指针异常的)

Object类是java所有类的基类,所有的类可以重写equals方法,所以一般可以把equals方法分为两种情况:

	1.没有重写equals方法,使用父类Object的原始equals()方法。
	2.重写equals方法,通常有必要重写hashcode().(java语言的规范)。

1.先介绍Object的equals方法,源码如下

		 public boolean equals(Object obj) {
       		 return (this == obj);
           }

从源码我们可以看出,Object类的equals()方法是和"= ="运算符一样的。所以类没有重写equals方法的话,equals() 和= =完全一样。
示例代码:

	public class Car{
		private int size;
		private int speed;
		public Car(){}
		public Car(int size,int speed){
			this.size=size;
			this.speed=speed;
			}
		//get、set方法省略就不贴上了
		}
	--------------------------------------
	public class Test{
		public static void main(String[] args){
			Car bmw=new Car(4,60);
			Car ben=new Car(4,60);
			
			System.out.println(bmw==ben);  //false
			System.out.println(bmw.equals(ben));  //false
			
		}
	}

**说明:new 一个对象会在堆里面存放一个实例,引用变量(bmw,ben)存放的是对应的地址,所以虽然两个对象表面上看是等价的,但是内存地址不一样。
然而,我们有时候需求是比较两个对象的各个属性值相等就看作等价,该怎么办呢?
这时候我们就要重写equals()方法了。上面第2点提到了,重写了equals方法,也需要重写hashCode()方法(原因也在后面)。

2.重写equals方法
实例代码

	public class Car{
		private int size;
		private int speed;
		public Car(){}
		public Car(int size,int speed){
			this.size=size;
			this.speed=speed;
			}
		@override
		public boolean equals(Object obj){
			if(this==obj) return true;   //先检查是不是同一个对象的引用
			if(obj==null || this.getClass() != obj.getClass()) return false;
			//再检查是否为null,(任何不为null对象equals(null)都返回false)
			//再检查两个对象是否为同一个类,不是则返回false。
			Car car=(Car)obj;
			if(this.size!=obj.size) return false;
			return this.speed==obj.speed;
			//假如我们没有重写hashCode方法
		}
	}
	--------------------------------------------
	public class Test{
		public static void main(String[] args){
			Car bmw=new Car(4,60);
			Car ben=new Car(4,60);
			
			System.out.println(bmw==ben);  //false
			System.out.println(bmw.equals(ben));  //true
			
		}

上面代码也可以再次体会equals()方法 和 == 运算符的区别。

equals()方法是可以改变的,根据自己的需求,那为什么说equals()方法重写后,一般有必要重写hashCode()方法?
这就联系到java中的集合部分。
上述重写例子两个对象,这两个对象我们设计equals()方法判断他们是等价的,我们希望在集合中只添加一个对象,如果散列值不同,集合中会添加两个等价对象。

参考
在java中,大家可以查看包装类,和String类的源码。他们都重写了equals()方法和hashCode()方法。 包装类还涉及到缓存池的内容,值得大家好好去看看,能对其有更好的理解。
String类:

	public boolean equals(Object anObject) {
       if (this == anObject) {
           return true;
       }
       if (anObject instanceof String) {
           String anotherString = (String) anObject;
           int n = value.length;
           if (n == anotherString.value.length) {
               char v1[] = value;
               char v2[] = anotherString.value;
               int i = 0;
               while (n-- != 0) {
                   if (v1[i] != v2[i])
                           return false;
                   i++;
               }
               return true;
           }
       }
       return false;
   }
    public int hashCode() {
       int h = hash;
       if (h == 0 && value.length > 0) {
           char val[] = value;

           for (int i = 0; i < value.length; i++) {
               h = 31 * h + val[i];
           }
           hash = h;
       }
       return h;
   }

总结

equals()是一个方法,我们可以根据自己的需求重写这个方法。 一般就是重写为判断两个对象所有属性值都相同则为等价,否则equals这个取名就没有意义了。

而==运算符 对于引用类型来说就是比较两个对象的内存地址。
对于基本类型来说,就是比较两个基本类型变量的值了。 具体可以参考周志明的《深入理解java虚拟机》,底层的东西才是基础。

equals方法被重写,hashCode()也应该重写。保持两个对象等价,散列值相等的原则。

分享一个大佬的博客:https://github.com/CyC2018/CS-Notes
你会受益匪浅的!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值