面试题:请谈谈”==“和equals的区别。
“==” 介绍
"==“是一个判断符号,作用就是判断对象地址是否相等,在此之前我们曾经探讨过一个话题,在Java中是值传递还是引用传递这个话题:
其实不管是值还是引用地址,我们都是将其看成一个”值“的改变。
所以使用”==“来判断的时候分两种情况:
1、基本数据类型—>比较值。
2、引用数据类型(复合数据类型)—>比较对象内存地址。
比较内存地址的例子:
String s1 = "1";
String s2 = "1";
s1 == s2; //true
分析: 首先创建s1字符串,会将该字符串对象放入字符串缓冲池中,接着创建s2字符串的时候,不会重新去new一个新的字符串对象,而是去引用字符串缓冲池中的s1对象上的值,也就是两者的对象地址相等。
能够清晰的了解Java中的引用地址这个概念,在运用”==“的时候也就了如指掌。
对于String缓冲池不了解可以阅读:
在笔试的时候有可能让你写出全部的基本数据类型:
byte,short,char,int,long,float,double,boolean.
==本身是一个符号,了解其作用即可,没啥好说的了,来看看equals。
equals() 介绍
equals()方法来自Object:
public boolean equals(Object obj) {
return (this == obj);
}
从源码可以看出它的作用也是判断对象是否相等。
由于Object是所有类的基类,也就是说Java中的所有类都会实现Object中的equals()方法,实现是implements的意思不是继承,可别搞错咯,实现对应的是重写,也就说我们可以重写该方法的实现,但是本意不能改变。
重点在于重写这里,我们可以重写equals()方法,来根据我们的意愿去实现它,例如实现为只要引用(对象内容)是相等的就返回true,通俗的说就是我们定义两个完全不一样的对象,但是两个对象上存放的值一样,没有重写就本意还是”==“的用法,就会返回false,但是我们如果重写equals() 方法,实现自己的要求,就能够让其返回成true,String字符串对象就是重写了equals()方法,利用常量池,字符串值相等也是返回true。
注意事项:在谈equals()的时候,我都是围绕对象这个概念来讲的,固在基本数据类型不受用。
面试题:谈谈equals()和hashCode()的区别,你重写过它们吗,你知道为什么重写equals必须重写hashCode()吗?
hashCode
对于hashCode()方法同样来自Object中:
public native int hashCode();
也就是说,在Java中所有类都会默认实现hashCode()方法,hashCode的作用也是判断两个对象是否相等。
那么为什么要出现两个**“重复”**的方法呢?
在Object中的equals()源码注释中有这样一句话:
Note that it is generally necessary to override the {@code hashCode} method whenever this method is overridden, so as to maintain the general contract for the {@code hashCode} method, which states
that equal objects must have equal hash codes.
意思就是我们在重写equals的时候需要重写hashCode()方法,并且规定了相同的对象必须要有相同的hashCode。
那么如果hashCode相等,对象一定相等吗?
答案:不一定(hash冲突)。
什么时候相等?
利用equals()再去对hashCode进行判断,如果相等则相同hashCode的两个对象是真的相等。
性能的考虑:
通过equals()判断的两个对象相等,那么hashCode一定相等,这样就不用通过hashCode()方法去判断hashCode是否相等了,但是在大多情况下都是hashCode相等对象就相等,很少出现不相等情况,很多时候不需要那么的全面,所以就会有下面这一种情况:
首先使用hashCode()方法来判断两个对象的hashCode是否相等,如果相等再通过equals进行比较,如果不相等则能够说明两个对象不相等。
这样性能就更加优化了。
其实到了这里我们就能得出结论了,其实探讨来探讨去也就是一个包含关系的问题。
如果重写了equals,是我们自己的实现方式,可能不是同一个对象那么它们的hashCode就肯定不是相同的,所以为了避免这类结果的出现,我们需要事先来判断hashCode,也就是说为什么要重写hashCode()方法的原因了。
对于这个问题是应用于什么场景下?
其实上面这个面试题,在很多情况下,equals和hashCode没有半毛关系,主要还是应用在hash容器中。
我们在判断的时候经常能够看到这样一行代码:(以HashMap源码为例)
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
首先判断hashCode是否相等,再用equals去判断,因为&&的优先级要高于||。
在实际开发中,可以根据具体需求去重写到底返回true还是false。