`
yuwenlin2008
  • 浏览: 124985 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Object类的equals方法和hashCode方法

阅读更多

Object 类是所有类的父类,Object类中定义了很多重要的方法,有些基础方法是必须要搞清楚的,今天我们就来学习下Object类中的equals方法和hashCode方法。

 

一、equals方法

首先我们来看下Object类的equals方法的源码:

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

很明显它是比较两个对象的引用(即内存地址)是否相等。如果你不知道这个,想当然的以为它比较的是内容,比如我们要比较两个用户对象是否相等:

User实体类:

public class User {
	
	private int userId;
	private String userName;
	private int age;
	
	public User(int userId, String userName, int age) {
		this.userId = userId;
		this.userName = userName;
		this.age = age;
	}
	
	public int getUserId() {
		return userId;
	}
	public void setUserId(int userId) {
		this.userId = userId;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

测试代码: 

public class UserTest {
	
	public static void main(String[] args) {
		User u1 = new User(1, "z3", 25);
		User u2 = new User(1, "z3", 25);
		boolean b = u1.equals(u2);
		System.out.println(b);
	}

}

执行结果为:false,为什么呢,因为你调用的是Object类的equals方法,它比较的是两个对象的引用,即内存地址,在Java虚拟机的堆上是两块独立的内存空间,绝对不相等的。并不是我们想要的结果,那应该要怎么做呢?自己重写Object类的equals方法就好了:

我们在User实体类中添加equals方法:

        @Override
	public boolean equals(Object obj) {
		if (obj == null)
			return false;
		if(obj instanceof User) {
			User other = (User) obj;
			if (age != other.age)
				return false;
			if (userId != other.userId)
				return false;
			if (userName == null) {
				if (other.userName != null)
					return false;
			} else if (!userName.equals(other.userName))
				return false;
		}
		return true;
	}

再次执行测试代码,结果为:true

我们可以看到重写的equals方法,比较了User类的每一个成员变量,那成员变量之间怎么比较呢,如果是基本数据类型如int,float,double,boolean等,直接比较其值就行了。

如果是字符串,直接调用字符串的equals方法即可,因为String类帮我们重写了equals方法,我们来看它的源码:

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;
    }

 可以看出String类的eqauls方法比较的是每一个char字符。其实查看Jdk源码,可以发现,各基本数据类型的包装类如Integer,Float,Double,Boolean等都重写了Object类的equals方法。因为实际业务需要我们去比较对象或变量的内容而不是引用。

 

二、hashCode方法

Object类的hashCode方法源码如下:

public native int hashCode();

它是一个本地方法,返回一个int类型的整数。 

Java为每一个对象提供一个int类型的hashCode,其目的是快速查找定位对象,猜测啊,在底层有一张Hash表,存储对象的hashCode和内存地址的映射,这样方便JVM在内存中能够快速查找定位到某个对象,不然,内存中那么多的对象,JVM如何查找一个对象呢。

 

hashCode有几个重要特性:

1.hashCode是为了查找对象或元素提高性能

2.如果两个对象equals相等,那么两个对象的hashCode一定相等

3.如果两个对象的hashCode相等,两个对象的equals不一定相等

4.如果要重写对象的equals方法,尽量要重写对象的hashCode方法

 

接下来,我们一一说明:

第1点,hashCode是为了查找对象或元素提高性能,这在上面已经说了JVM要查找内存中的对象可以快速定位。还有就是集合类的实现,比如Set集合,元素不允许重复,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。于是采用Java的哈希表原理,先根据元素的hashCode定位元素位置,如果该位置元素不存在,则将元素插入集合的该位置,如果已经存在,则equals比较其内容,如果内容一致则元素重复了,否则采用链式数据结构存储到该位置(HashMap的实现)。

 

第2点,如果两个对象equals相等,那么两个对象的hashCode一定相等。这个上面的Set集合就已经解释了,如果两个对象equals相等,hashCode不相等,那么根据Set集合实现会将两个元素存储到不同的位置,那么这就违背Set集合元素不允许重复了。

 

第3点,如果两个对象的hashCode相等,两个对象的equals不一定相等。这个我们看下Set的实现HashSet,其底层是HashMap的实现:

public V put(K key, V value) {
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key.hashCode());
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
       Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

根据HashMap的put方法实现,我们可以看到首先根据key的hashCode计算出元素在哈希表的位置,如果该位置上已经有元素(说明这两元素的hashCode相等),再equals比较两元素的内容,如果不相等,则以链表的方式将两元素存储在该位置,这充分说明了两元素hashCode相等,但equals不一定相等。

 

第4点,如果要重写对象的equals方法,尽量要重写对象的hashCode方法,这个其实就是保证第2点的实现,如果不重写hashCode方法,还是以Set集合为例,就无法保证元素不重复。可以查看jdk源码,像String类,Integer类等只要重写了equals方法的,都重写了hashCode方法。

 

 

总结,我们在开发中,养成良好的习惯,每写一个实体类,就重写它的equals方法和hashCode方法,要么都不写,要写两个都要写,可以减少不必要的问题发生。

 

 

 

<audio controls="controls" style="display: none;"></audio>

0
0
分享到:
评论

相关推荐

    关于Object中equals方法和hashCode方法判断的分析

    今天小编就为大家分享一篇关于关于Object中equals方法和hashCode方法判断的分析,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

    hashcode和equals方法

    equals()和hashcode()这两个方法都是从object类中继承过来的。当String 、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法.

    Java理论与实践:hashCode()和equals()方法

    本文介绍了Java语言不直接支持关联数组,可以使用任何对象作为一个索引的数组,但在根Object类中使用 hashCode()方法明确表示期望广泛使用HashMap。理想情况下基于散列的容器提供有效插入和有效检索;直接在对象模式...

    Java的Object类讲解案例代码 equals()、hashCode()、finalize()、clone()、wait()

    Object类是所有Java类的根类,它定义了一些常用的方法,例如equals()、hashCode()、toString()等。本案例代码将详细展示Object类的使用方法,并提供一些实际场景下的案例,以帮助开发者更好地理解和运用这些方法。 ...

    探索equals()和hashCode()方法_动力节点Java学院整理

    equals():反映的是对象或变量具体...根类Object的hashCode()方法的计算依赖于对象实例的D(内存地址),故每个Object对象的hashCode都是唯一的;当然,当对象所对应的类重写了hashCode()方法时,结果就截然不同了。

    Java中hashCode和equals方法的正确使用

    在这篇文章中,我将告诉大家我对hashCode和equals方法的理解。我将讨论他们的默认实现,以及如何正确的重写他们。我也将使用Apache Commons提供的工具包做一个实现。  hashCode()和equals()定义在Object类中,这...

    深入理解equals和hashCode方法

    在Java中,equals和hashCode方法是Object中提供的两个方法,这两个方法对以后的学习有很大的帮助,本文就深度来去讲解这两个方法。下面小编带大家来一起学习吧

    Java equals 方法与hashcode 方法的深入解析

    PS:本文使用jdk1.7解析1.Object类 的equals 方法 代码如下: /** * Indicates whether some other object is “equal to” this one. *  * The {@code equals} method implements an equivalence relation * on ...

    学习Object类——为什么要重写equeals和hashcode方法

    个人学习终结成果:为什么要重新equals和hashCode方法?如何重写?站好马步需从j2se基础开始

    why在重写equals时还必须重写hashcode方法分享

    首先我们先来看下String类的源码:可以发现String是重写了Object类的equals方法的,并且也重写了hashcode方法

    java集合——Java中的equals和hashCode方法详解

    本篇文章详细介绍了Java中的equals和hashCode方法详解,Object 类是所有类的父类,非常具有实用价值,需要的朋友可以参考下。

    为什么在重写 equals方法的同时必须重写 hashcode方法

    Object 类是所有类的父类,其 equals 方法比较的是两个对象的引用指向的地址,hashcode 是一个本地方法,返回的是对象地址值。他们都是通过比较地址来比较对象是否相等的

    java中hashCode、equals的使用方法教程

    hashCode()和equals()定义在Object类中,这个类是所有java类的基类,所以所有的java类都继承这两个方法。下面这篇文章主要给大家介绍了关于java中hashCode、equals的使用方法,需要的朋友可以参考下。

    第十一章 Object类和包装类.md

    ==与equals的比较,包装类的使用

    面试官瞬间就饱了,重写equals函数,需要重写hashCode函数吗?

    String重写了equals方法,引用指向同一个地址,一定返回true。并且如果String包含的字符串 完全相同,同样返回true. public boolean equals(Object anObject) { if (this == anObject) { return true; } /

    解析Java对象的equals()和hashCode()的使用

     在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,要设计另外一个。在多数情况 下,这两个函数是不用考虑的,直接使用它们的默认设计可以了。但是在一些情况下,这两个...

    javaee_tedu_day09.zip

    如果不是想使用object类,toString方法,可以重写此方法 equals方法 equals方法比较对象的是否相同 ==比较两个对象的内存地址 如果想表示对象的内容相同,返回true,则重写此方法 hashCode 返回一个hash code码,...

    java object

    java hashcode equals 方法的作用 面向对象下object类中的方法

    java 面对对象编程.pdf.zip

    面向对象基础 面向对象和面向过程的区别 成员变量与局部变量的区别 ...String#equals() 和 Object#equals() 有何区别? 字符串常量池的作用了解吗? String s1 = new String("abc");这句话创建了几个

    Java Object 类高难度进阶版面试题集锦解析Java Object类高难度面试题及答案解析

    提供了20道高难度的Java Object类面试题及详细答案解析,涵盖了equals()、hashCode()、toString()、clone()、finalize()等方法的重写和应用,以及对象的比较、克隆、标识哈希码等概念。适合准备Java面试的开发者深入...

Global site tag (gtag.js) - Google Analytics