当前位置:网站首页>equals()与hashCode()

equals()与hashCode()

2022-07-06 16:54:00 一个很懒的人

本文主要介绍了hashCode()与equals()的原理,并在讲述了重写二者的方法体,以及其在集合中的使用(保证集合中对象内容不重复!)

前言


在java中有一个共同的父类 Object ,所有对象均隐性继承了此类,其中 equals()hashCode() 就是继承过来的方法。


equals() 默认在比较两个对象时,比较的是其地址(因为所有类继承Object,Object其内部使用的是==比较,==用于判断两边的内存地址是否相同)
eg:person01.equals(person02)是在判断两个对象在内存堆中的地址是否相同。由于是继承父类的方法,我们在编写程序时自然可以重写此方法,我们熟知的String在其内部就已经重写了equals方法(自己定义的类默认未重写),如下所示!


hashCode() 与equals()相似,但其是用native修饰的方法(下面会有解释),它默认返回的是一个整数(jvm默认有一些契约,各厂商默认都会遵循此契约,下面会有解释),但自定义的类都默认继承Object,自然也可以重写hashCode()方法(在TreeSet中存储对象会使用此方法,下面会有详解!)


  • Object中equals()与hashCode()方法
    在这里插入图片描述
  • 一个native方法就是一个Java调用非Java代码的接口。一个native方法是指该方法的实现由非Java语言实现,比如用C或C++实现。在这里插入图片描述
  • 自定义类中equals()与hashCode()方法(未重写)
    在这里插入图片描述
  • String内部重写的equals方法
    在这里插入图片描述

1.equals()

(1)equals()简介

equals()在不重写时,默认继承Object的方法,在Object的equals()使用 == 判断,==判断的是两个对象的地址是否相同,String是个例外其在内部重写了equals方法,所以可以使用equals()方法判断字符串内容是否相等,在我们自定义的类中可以重写equals方法,实现对自定义对象内容的判断!

(2)equals()重写(实现对自定义类对象内容是否相等的判断)

步骤:

  1. 判断此对象与传过来对象的地址是否相同
  2. 使用instanceof判断类型
  3. 根据类型结果(可能是,也可能不是),进行类型转换,比较各属性值

代码示例如下:

	
	@Override
	public boolean equals(Object obj) {
    
		// TODO Auto-generated method stub
		
		//判断此对象与传过来对象的地址是否相同
		if (this==obj) {
    
			return true;
			//判断obj是否属于Person类
		}else if (obj instanceof Person) {
    
			//如果是,父类转子类
			Person p=(Person)obj;
			//判断各个属性是否相同
			if (p.name.equals(this.name)&&p.age==this.age) {
    
				return true;
			}
		}		
		//不相同返回false
		return false;
	}
	

2.hashCode()与内存地址

结论: hashCode返回的并不一定是对象的(虚拟)内存地址,只是可能会与内存地址有关,具体取决于运行时库和JVM的具体实现。

(1)native

native主要用于方法上

  1. 一个native方法就是一个Java调用非Java代码的接口。一个native方法是指该方法的实现由非Java语言实现,比如用C或C++实现。
  2. 在定义一个native方法时,并不提供实现体(比较像定义一个Java Interface),因为其实现体是由非Java语言在外面实现的
  • 注意:
    主要是因为JAVA无法对操作系统底层进行操作,但是可以通过jni(java native interface)调用其他语言来实现底层的访问。

(2)Object.hashCode()

参考:Java的Object.hashCode()的返回值到底是不是对象内存地址?


Object.hashCode是一个native方法,看不到源码(Java代码,Oracle的JDK是看不到的,OpenJDK或其他开源JRE是可以找到对应的C/C++代码)。


Object.hashCode()在JRE(Java Runtime Library)中应该遵循的一些契约(contract):(PS:所谓契约当然是大家一致达成的,各个JVM厂商都会遵循)

  • 一致性(consistent),在程序的一次执行过程中,对同一个对象必须一致地返回同一个整数。
  • 如果两个对象通过equals(Object)比较,结果相等,那么对这两个对象分别调用hashCode方法应该产生相同的整数结果。(PS:这里equals和hashCode说的都是Object类的)
  • 如果两个对象通过java.lang.Object.equals(java.lang.Ojbect)比较,结果不相等,不必保证对这两个对象分别调用hashCode也返回两个不相同的整数。

(3)特殊hashCode

  • String:只要字符串内容相同,hashCode也相同。
  • Integer:返回的hashCode是其对象内包含的整数的值。

(4)重写Object.hashCode()

	@Override
	public int hashCode() {
    
		// TODO Auto-generated method stub
		
		//返回属性的hashCode,不使用jvm默认契约返回的hashCode值
		//字符串只要值相等,其hashCode值就相等
		int numName=this.name.hashCode();

		return numName+this.age;
	}

3.hashCode()与equals()在集合中的使用

  • 如果两个对象equals()为true,那hashCode一定相同,反过来不成立,即如果两个对象hashCode相同,不能得出这两个对象相等。
  • 如果用对象当做Map的key,或在Set集合中存储数据时(若要保证值的唯一性),那么就要同时重写hashCode和equals()才行,而且要保证两者的一致性。
    原因:(在Set集合添加数据时,会先判断新添加的数据与集合内原有的数据的调用hashCode()方法判断hashCode值是否相等,若不相等直接将新元素添加进集合内,若相等再调用equals()方法判断其结果是否为true,若为true则不添加,false则添加)
  • 代码示例:

测试结果:
在这里插入图片描述

Test.java

public class Test {
    
	public static void main(String[] args) {
    
		Person person01=new Person("张三", 18);
		Person person02=new Person("张三", 18);
		Person person03=new Person("李四", 18);
		
		HashSet<Person> hashSet=new HashSet<Person>();
		hashSet.add(person01);
		hashSet.add(person02);
		hashSet.add(person03);
		
		Iterator<Person> iterator=hashSet.iterator();
		while(iterator.hasNext()) {
    
			Person person=iterator.next();
			System.out.println(person);
		}
		
	}
}

Person.java

package day15.demo01;

public class Person {
    
	private String name;
	private int age;
	
	public Person(String name, int age) {
    
		super();
		this.name = name;
		this.age = age;
	}
	public Person() {
    
		super();
	}

	@Override
	public String toString() {
    
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	@Override
	public boolean equals(Object obj) {
    
		// TODO Auto-generated method stub
		
		//判断此对象与传过来对象的地址是否相同
		if (this==obj) {
    
			return true;
			//判断obj是否属于Person类
		}else if (obj instanceof Person) {
    
			//如果是,父类转子类
			Person p=(Person)obj;
			//判断各个属性是否相同
			if (p.name.equals(this.name)&&p.age==this.age) {
    
				return true;
			}
		}		
		//不相同返回false
		return false;
	}
	
	@Override
	public int hashCode() {
    
		// TODO Auto-generated method stub
		
		//返回属性的hashCode,不使用jvm默认契约返回的hashCode值
		//字符串只要值相等,其hashCode值就相等
		int numName=this.name.hashCode();

		return numName+this.age;
	}
}

原网站

版权声明
本文为[一个很懒的人]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_43715360/article/details/125574455