当前位置:   article > 正文

有关equal及equals重写知识点(完全掌握这一篇够了)_.equals()和equals.("")

.equals()和equals.("")

我不想过庸庸碌碌、平平淡淡的一生,我这一生我想总该要做出一些成绩,以不至于到老闲暇时候回首过往满是后悔,不想到了父母爱人病倒需要钱的时候,满是无奈与自责,不想到了为人父母时老婆孩子有想买的礼物的时候,沉默不语无法满足;

目录

“==”和equals 区别:

基本类型和引用类型的区别:

         String类中重写equals源码:

为什么要进行强转呢?、

instanceof是什么?

JAVA语言规范要求equals方法具有下面的特性:(非空对象)

相等测试与继承:

完美的equals方法建议:

instanceof 与getClass比较:

instanceof和getClass总结

         Equals与hashcode:


“==”和equals 区别:

    “==”是运算符,如果等号两边是基本数据类型(八种基本数据类型),则比较的是存储的值;如果是引用数据类型,则比较的是所指向对象的地址值。

  • 还可以如何区分基本类型和引用类型呢?可以看它存的是什么,如果是实体值就是基本类型,如果存的是地址就是引用类型,后文有详细区分;

    equals是Object类中的方法,所有java类都直接或者间接继承object类,它比较的是所指向的对象的地址值,一般情况下,重写之后才比较的是对象存储的值(。

  •  特别的像String、Date、File、包装类中都重写了object中的equals()方法,这时候他们比较的就不是指向的地址值了,而是对象本身指向的实体内容。

总结:“==”是运算符
①如果比较的对象是基本数据类型,则比较的是其存储的值是否相等;
②如果比较的是引用数据类型,则比较的是所指向对象的地址值是否相等(是否是同一个对象)。

equals();
equals是Object类中的方法,如果没有被重写就是用来比较两个对象的地址值是否相等。

  1. public boolean equals(Object obj) {
  2.         return (this == obj);
  3.     }

基本类型和引用类型的区别:

  •    基本类型有八个:byte\ int\ double \float\ short\ long\ char \boolean

  •    而引用类型,可以简单理解为就是对象(例如String、date类等)。

注意:

        equals 方法不能用于比较基本数据类型,如果没有对 equals 方法进行重写,比较的是引用类型的变量所指向的对象的地址值:错误示例如下:

  1. int a=1;
  2. int b=1;
  3. System.out.println(a.equals(b));
  4. //不能运行,会直接报错,因为equals方法不能用于比较基本数据类型

        一般情况下,类会重写equals方法用来比较两个对象的实体内容(即对象具体的值)是否相等。比如String类中的equals()是被重写了,比较的是对象的值。

        对上面标黄色标记补充:(在黄色标记的地方,我们可能会想到我们为什么要去重写equals方法呢?因为equals方法时声明在超类object中的,所有Java类都继承了object类,呢么也就可以使用object类中的方法,在不重写的情况,我们调用equals方法,比较的是对象的地址值,此时的equals方法与“==”作用是一样的);

String类中重写equals源码:

  1. public boolean equals(Object anObject) {
  2. if (this == anObject) {
  3. return true;
  4. }
  5. if (anObject instanceof String) {
  6. String anotherString = (String)anObject;
  7. int n = value.length;
  8. if (n == anotherString.value.length) {
  9. char v1[] = value;
  10. char v2[] = anotherString.value;
  11. int i = 0;
  12. while (n-- != 0) {
  13. if (v1[i] != v2[i])
  14. return false;
  15. i++;
  16. }
  17. return true;
  18. }
  19. }
  20. return false;
  21. }

        笔记:String类的底层其实是char数组。

        总结 :“== ”对于基本类型来说是值比较,对于引用类型来说是比较的是地址值;  而 equals 默认情况下是引用比较,只是很多类重写了 equals 方法,比如 String、Integer 等,引用比较变成了值比较,所以在被重写的情况下 equals 比较的是值是否相等,通常我们自定义的Java类也是会这样重写的,使equals方法去比较两个对象的实体值是否相等。

我们再对以下代码分析(下面的代码是上面代码中截取的片段)

  1. if (anObject instanceof String) {
  2. String anotherString = (String)anObject;
  3. int n = value.length;

在代码的第二行我们为什么要进行强转呢?

  • 原因:要将要比较的对象向下转换,这样才能访问子类的方法,才能比较子类的方法

instanceof是什么?

  • instanceof 作用是:判断一个引用类型变量所指向的对象是否是一个类(或接口、抽象类、父类)的实例,即它左边的对象是否是它右边的类的实例,该运算符返回boolean类型的数据。

  • 在上面代码中,第一行的 instanceof 判断——> 判断 anobject 和 String是否为同一类型的类, 不是的话就不能相比较,自然不相同

对象编程有两个重要的相等概念:值相等和引用相等。值相等的意思是它们的数据成员按内存位分别相等。引用相等则是指它们指向同一个内存地址。引用相等必然推出值相等,值相等却未必能推出引用相等对于基本类型关系等号“==”判断两者是否值相等(结构类型和枚举类型没有定义关系等号“==”,我们必须自己定义)。对于引用类型关系等号“==”判断两者是否引用相等。

JAVA语言规范要求equals方法具有下面的特性:(非空对象)

  • 自反性:对于任何非空引用x,x.equals(x)应该返回true
  • 对称性:对于任何引用x,y,如果x.equals(y)返回true那么y.equals(x)也应该返回true
  • 传递性:对于任何引用x,y,z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true。一致性:如果x和y引用的对象没有发生变化,反复调用x.equal(y)应该返回同样的结果。
  • 一致性:对于x,y引用的对象没有发生变化,那么反复调用x.equals(y)应该返回相同的结果
  • 对于任何非空引用x,x.equals(null)应该返回false。

相等测试与继承:

        1.如果子类能够拥有自己的相等的概念,则对称性需求将强制采用getClass进行检测。

        2.如果由父类决定相等的概念,那么就可以用instanceof进行检测,这样可以在不同子类的对象之间进行相等的比较

完美的equals方法建议:

1.  显示参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量。

2.  检测this与otherObject是否引用同一个对象。 if(this == otherObject)

3.  检测otherObject是否为null,如果为 null ,返回 false。这项检测是很必要的。

instanceof 与getClass比较:

4.  比较this与otherObject是否属于同一个类。如果equals的语义在每一个子类中有所改变,就使用getClass 检测 ——if(getClass() != otherObject.getClass()) return false;

如果所有子类都有相同的相等性语义,可以使用instanceof检测——if(otherObject instanceof ClassName) return false;

instanceof 是Java的一个二元操作符(运算符),也是Java的保留关键字。它的作用是判断其左边对象是否为其右边类的实例(子类的对象也是父类的),返回的是boolean类型的数据。用它来判断某个对象是否是某个Class类的实例。

与之对应的是getClass方法:getClass()是object类中的方法,可返回Class类型的实例(返回对象所属的直接类),对其调用其他的方法,可以获得当前类的各种信息

5.  将otherObject转换为相应的类类型变量。

ClassName  other= (ClassName)otherObject

①为什么要进行强制类型转换?

答:要将要比较的对象向下转换,这样才能访问子类的方法,才能比较子类的方法

②子类对象被强制转换成父类之后,还能不能访问子类属性?

答:能

6.  开始对所需要比较的成员变量进行比较,使用 == 比较基本类型域,使用equal比较对象域。如果所有的域都匹配,就返回 true;否则返回 false 。

7.  如果子类中重新定义equals就要在其中包含调用super.equals().

  1.         public boolean equals(Object obj) {
  2.                 if(this == obj) return true;
  3.                 if(obj == null) return false;
  4.                 if(this.getClass() != obj.getClass()) return false;    //子类中equals方法
  5.                 if(!(obj instanceof Object)) return false;            //父类中equals方法
  6.         }

euals与hashCode的定义必须一致:如果x.equals(y) == true,那么x.hashCode() = y.hashCode();

在子类中定义equals方法时,首先要调用父类的equals方法,如果父类中的属性都相等,就需要比较子类中的属性

用instance of 的缺陷,比如说父类引用子类的对象,但是子类的对象拥有和父类某个对象相同的属性,如果没有考虑子类特有的信息,则instance of 就不怎么好。

如果子类能够拥有自己的相等的概念,那么对称性需求将强制采用getClass进行检测。如果父类决定相等的概念,那么就可以使用instanceof进行检测,这样就可以在不同的子类的对象之间进行相等比较。

instanceof和getClass总结

区别就是getClass()限制了对象只能是同一个类,而instanceof却允许对象是同一个类或其子类。

Equals与hashcode:

Java中,为什么大家都说重写了equals方法都要进而重写Hashcode方法呢?

原因是以下两个:

(1)java的hashcode有一个通用的协定,即相等的对象必须具有相等的散列码(hashCode)。

如果不重写hashcode会违反这个协定。

(2)对于HashSet和HashMap这些基于散列值(hash)实现的类。HashMap的底层处理机制是以数组的方法保存放入的数据的(Node<K,V>[] table),其中的关键是数组下标的处理。数组的下标是根据传入的元素hashCode方法的返回值再和特定的值异或决定的。如果该数组位置上已经有放入的值了,且传入的键值相等则不处理,若不相等则覆盖原来的值,如果数组位置没有条目,则插入,并加入到相应的链表中。检查键是否存在也是根据hashCode值来确定的。所以如果不重写hashCode的话,可能导致HashSet、HashMap不能正常的运作

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/573410
推荐阅读
相关标签
  

闽ICP备14008679号