关于JAVA核心技术(卷一)读后的思考(equals方法的讨论)

这是我反复看了两遍才理解的部分。其中也不乏参考了他人的微博内容,才大致对这个方法有所理解。

首先我们从Object类开始说起,

书中已经说了Object类是Java中所有类的始祖,在Java中的每个类都是由他扩展而来的,但在现实使用中并没有要求写出。如果一个类并没有明确指出超类,Object就是被认为是这个类的超类。

可以用Object类型的变量引用任何类型的对象:

Object obj = new Employee("Harry Hacker",35000);

正如昨天的博文所提到过的,Object只是用作各种值的通用持有者,是无法对其中的内容进行操作的,如果想要对其进行操作的话,需要弄清对象的原始类型,并对其进行类型转换。如:Employee e = (Employee)  obj;

知道这些我们就可以来提一提equals方法了;

在java中,对于基本数据类型,判断它们是否相等是通过“==”来进行判断的,而equals方法是用于检测一个对象是否等于另外一个对象的。在Object类中这个方法是判断两个对象是否具有相同的引用。但这种判断在大部分情况下是没有意义的,因为我们经常要检测的是两个对象状态的向邓姓,如果两个对象状态相等了,就表示相等了。

例如,若两个雇员对象的姓名、薪水和雇佣日期都一样,就认为它们是相等的。

其中equals代码实现如下:

public class Employee{

……

public boolean equals (Object otherObject){

if(this==otherObject)                                                      //首先判断是否具有相同的引用

return true;

if(othterObject==null)                                                    //判断显式参数是否为空

return false;

if(getClass()!=otherObject.getClass())                         //判断二者是否属于相同的类

return flase;

Employee other=(Employee)otherObject;                     //把显式参数类型转换成相同类型,这样可以对其进行操作

return name.equals(other.name)&&salary==other.salary&&hireDay.equals(other.hireday);

}

}

相等测试与继承

在上面的代码,我们会想到一个问腿,若隐式参数和显示参数不属于同一个类,equals方法将如何处理?

这时候我们就会引出另一个关键字instanceof,当时我看书的时候是不能理解书上想表达的意思。因为instanceof这个关键字可能是第一次出现在书本上,而我在前面的学习中并没有印象,所以我当时就是网上查阅资料,至于正确性我也不敢保证,但是我如果按照他的解释是可以解释的通的,所以我先在这里列出来:

java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。

了解这个关键字之后我们还要知道Java语言贵伐要求equals方法具有以下特性:

1)自反性:对于任何非空引用x,x.equals(x)都应返回true

2)对称性:对于任何引用x和y,当且仅当y.equals(x)返回true,x.equals(y)也应该返回true。

3)传递性:对于任意引用,x、y、z,如果x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)也应返回true。

4)一致性:如果x和y引用的对象没有发生变化,反复调用x.equals(y)应该返回同样的结果。

5)对任意非空引用x,x.equals(null)应该返回false。

了解这些之后,就会出现一个问题:

若出现e.equals(m),这里的e是一个Employee对象,m是一个Manager对象,并且两个对象具有相同的姓名,薪水和雇佣日期。

这样的话,如果在Employee.equals中用instanceof进行检测,则会返回出,而反过来调用因为对称性的原因,也应该返回true。所以我们就给出一个完美的equals方法的建议:

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

2)检测this和otherObject是否引用同一对象:

if(this==otherObject)

return true;

3)检测otherObject是否为null,如果为null,返回false。

4)比较this和otherObject是否属于同一个类。如果equals的语义在每个子类中有所改变,如果equals的语义在每个子类有所改变,就使用getClass()检测。

if(getClass()!=otherObject.getClass())

return  false;

这里有必要解释一下getClass()方法的原理了:

即返回:

表示此对象的运行时类的类对象。

同时我还举了例子以此说明:

public class GetclassDemo {

public static void main(String[] args) {
        // TODO Auto-generated method stub
        Employee e=new Employee();
        Manager m=new Manager();
        e.setId(1);
        m.setId(1);
        
    
        
        if(m.getClass()==e.getClass()) {
            System.out.println("yes");
        }else
        {
            System.out.println("no");
        }
        if(m.equals(e)) {
            System.out.println("yes");
        }else
        {
            System.out.println("no");
        }
        if(m instanceof Employee) {
            System.out.println("yes");
        }else {
            System.out.println("no");
        }

}

}
结果:

class com.java.getclassDemo.Employee
++++++++++
class com.java.getclassDemo.Manager
++++++++++
class com.java.getclassDemo.Manager
no
no
yes

下面来分析一下,第一二行是初始化Employee时调用的getClas()方法

此时为Employee,

第三四排为调用子类Manager的构造函数时同时会调用其超类的构造函数,再调用自己的getClass();

而后面第二个no表示二者表示的状态并不一样,而第三个yes表示m确实为Employee的子类,也从侧面证明上文说到的方法是正确的。  

回到正文。接下来时如果所有子类拥有同一语义,则可以用instanceof检测。

5)将otherObject转换为相应的类类性变量。

这里的类型转换我觉得有个博主解释的特别好

https://blog.csdn.net/heidou369/article/details/80414904

但是对于getClass()我并不赞同他的看法,在这里我也不知道谁对谁错

6)接下来对所有的需要匹配的域进行匹配就可以了。

原文地址:https://www.cnblogs.com/zzuzhouxiang/p/10336457.html

时间: 2024-11-13 15:01:16

关于JAVA核心技术(卷一)读后的思考(equals方法的讨论)的相关文章

关于JAVA核心技术(卷一)读后的思考(内部类的讨论)

内部类 内部类是定义在另一个类中的类. 定义内部类的原因有: 1)内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据. 2)内部类可以对同一个包中的其他类隐藏起来. 3)当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷. 使用内部类访问对象状态 分析一下下面一段代码 public class TalkingClock { private int interval; private boolean beep; public TalkingClock(int inter

java核心技术卷一

java核心技术卷一 java基础类型 整型 数据类型 字节数 取值范围 int 4 +_2^4*8-1 short 2 +_2^2*8-1 long 8 +_2^8*8-1 byte 1 -128-127       浮点类型 数据类型 字节数 取值范围 小数位数 float 4 10^-38~10^38和-10^-38~-10^38 小数位数6-7 double 4 10^-308~10^308和-10^-308~-10^308 15位小数         boolean 类型和char 类

java中如何实现一个优美的equals方法

java中的任何类都从老祖宗Object中集成了equals方法,在编程实践中应用使用equals方法判断两个对象是否相同的场景无处不在,所以我们在实现自己的类是必须重写出一个优美的equals方法. 首先让我们来看看java语言规范中对equals方法的说明,一个equals方法应当满足如下几个特性: 自反性,对任何一个非空的引用x,x.equals(x)必须返回true: 对称性,对任何引用x和y来说,如果x.equals(y)返回true,那么y.equals(x)也必须返回true: 传

读《java核心技术卷一》有感

过去一个多月了吧.才囫囵吞枣地把这书过了一遍.话说这书也够长的,一共706页.我从来不是个喜欢记录的人,一直以来看什么书都是看完了就扔一边去,可能有时候有那么一点想记录下来的冲动,但算算时间太紧,很多也是有始无终,毕竟在之前研究研究程序也只是自己的一个爱好而已,但没有想到签了一个程序员的工作.唉,这老天也太捉弄人了吧,让一个学电气工程(强电方向)学生毕业之后去写代码,而且是与硬件完全无关的代码.真是白念几年大学了.行了,就行发这么多牢骚吧. <java核心技术>有两个卷,我只看了卷一,从我的感

《Java核心技术卷一》笔记 多线程

有时,我们需要在一个程序中同时并行的处理多个任务,如播放器一边要播放音乐同时还要不断更新画面显示,或者是一边执行耗时任务,UI还能一边继续响应各种事件.还有的时候,一个任务需要很长时间才能完成,如果分成多份一起执行,可以极大的缩短需要的时间.多线程可以很好的解决这类问题. 一个程序(进程)如果可以同时执行多个任务,每个并行的任务都是通过一个线程来完成,这就是一个多线程程序.进程拥有自己的一整套数据(变量),各个线程共享进程的数据,线程间通信比进程间通信更简单,线程开销比进程小. Java中为多线

Java核心技术 卷一 笔记六 Date类

在Java核心技术卷就行了一前期  date类出现的频率很高  所以就对date类进行了小小的整合 Date类有两个 date类 表示特定时间的类 这个构造函数分配一个Date对象并初始化它代表指定的毫秒数,因为被称为"纪元",即1970年1月1日00:00:00 GMT标准基准时间. 就像格林尼治时间一样  作为一种基准值而存在 一般常用的是date转为string类型 String s=new Date(0).toString(); System.out.println(s.toS

Java核心技术卷一 4. java接口、lambda、内部类和代理

接口 接口概念 接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义. 如果类遵从某个特定接口,那么久履行这项服务. public interface Comparable<T>{ int compareTo(T other); } 任何实现 Comparable 接口的类都需要包含 compareTo 方法,并且这个方法的参数必须是一个 T 对象,返回一个整形数值. 接口的特点: 接口中所有方法自动地属于 public,所以接口的方法不需要提供关键字 public .

JAVA学习(二) String使用equals方法和==分别比较的是什么?(转)

String使用的equals方法和==的区别 equals方法和==的区别 首先大家知道,String既可以作为一个对象来使用,又可以作为一个基本类型来使用.这里指的作为一个基本类型来使用只是指使用方法上的,比如String s = "Hello",它的使用方法如同基本类型int一样,比如int i = 1;,而作为一个对象来使用,则是指通过new关键字来创建一个新对象,比如String s = new String("Hello").但是它的内部动作其实还是创建

java为什么要重写hashCode方法和equals方法?

之前发布过一篇文章说的是关于 equals方法重写 http://www.cnblogs.com/aL0n4k/p/4777333.html 下面就hashCode方法发表一下本人的理解,仅供参考,交流. 在 关于java重写equals方法 已经提及说,比较2个对象的时候,要比较他们各自的属性. 那么重写hashCode方法是因为我们在接触到集合的时候,里面有个Set接口,他只能添加无序以及不重复的对象元素. 那有人会问,既然是这样我们直接用equals判断不就完了么? 实际上对Set集合而言