• 关于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)接下来对所有的需要匹配的域进行匹配就可以了。

    如果有写的不对的地方,欢迎指正,希望能够共同进步,谢谢!
  • 相关阅读:
    (原创)c#学习笔记10--定义类成员01--成员定义06--自动属性
    (原创)c#学习笔记10--定义类成员01--成员定义03--定义属性
    (原创)c#学习笔记10--定义类成员01--成员定义02--建立方法
    【BZOJ3110】K大数查询(ZJOI2013)-整体二分+线段树
    【BZOJ3110】K大数查询(ZJOI2013)-整体二分+线段树
    【HDU5412】CRB and Queries-整体二分:带修改区间第K小
    【HDU5412】CRB and Queries-整体二分:带修改区间第K小
    【NOI2007T2】货币兑换-DP斜率优化+CDQ分治
    【NOI2007T2】货币兑换-DP斜率优化+CDQ分治
    【BZOJ3295】动态逆序对(CQOI2011)-CDQ分治:三维偏序
  • 原文地址:https://www.cnblogs.com/zzuzhouxiang/p/10336457.html
Copyright © 2020-2023  润新知