Java学习(继承)——Object类:所有类的超类

目录

Object类型的变量

equals方法

相等测试与继承

hashCode方法

toString方法


Object类型的变量

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

    Object obj=new Employee();
  • 但是Object类型的变量只是一个作为各种值的一个泛型容器。如果想要对其中的值进行具体的操作,还需要清除对象的原始类型并加以强制转换:

    Employee e=(Employee) obj;
    • 这时可以对·E进行一系列的操作

  • 在Java中,只有基本类型(数值,字符,布尔类型的值)不是对象

  • 像所有的数组类型,不管是对象数组还是基本类型的数组都扩展了Object类

    //对象数组
    Employee[] staff=new Employee[10];
    //基本类型的数组
    obj=new int[10];

equals方法

  • Object类的equals方法用于检测一个对象是否等于另一个对象

  • 在Object类中的equals方法用于确定两个引用是否相等

  • 可以看出,在Object类中的equals方法用于==去比较,那么==和equals有什么区别呢?

    • 图中可以看出在对基本类型进行赋值相同的值时用==进行比较结果是true,==实际比较的是两个对象的堆内存地址,像123,12.32,他们是作为常量在常量池中以HashSet策略存储起来的,图中的两个引用a,b实际是指向同一个对象地址的

    • 其中的字符串常量“123”,虚拟机在发现这个字符串常量之后,他会在内部的字符串常量列表中查找,如果没有找到,那么他会在堆里面创建一个包含字符串序列[123]的String对象s1,,然后把这个字符串序列和对象的String对象作为一个值对([123],s1)保存在字符串常量列表中

    • 在后面将“123”赋值给s2,这时虚拟机发现了一个相同的字符串常量123,它会在内部的字符串序列表找到相同的字符串序列然后返回对应的String对象引用,像String s2="123",运行时s2会从内部字符串常量列表内得到s1的返回值,所以s1和s2都指向同一个String对象

    • s3引用了对象new String();实际上new操作为新生的对象分配了内存,这不是引用,而是在Java堆中划出了一片内存供新生的对象。所以s3引用的和s1,s2引用的不同

    • Object的equals类的equals也同样是使用了==来比较两个对象,那么它们还有什么区别呢?

  • 其实Object类中的equals方法对于大多数类来说就已经足够了,但是,经常需要基于状态检测对象的相等性,如果两个对象有相同的状态才说这两个对象相同。例如两个员工对象,姓名,年龄,工种,工资,雇佣日期都相同,这样在实际的数据库中就需要比较两者的ID才有意义,否则,就认为这两个对象是相等的。

  • 这时就需要用到之前的方法的重写这个知识了,我们可以在Object类下我们自己的类中来重写equals方法,来实现我们自己的比较方法

    • 在这里的GetClass()方法将返回一个对象所属的类,只有两对象属于一个类时这两个对象才可能相等

    • 代码的最后一句的返回值,是在比较字段是否具有相同的值,使用Objects类的equals方法是为了防备name字段可能为null的情况。

  • 在子类中定义equals方法时首先要调用超类的equals,如果比较失败,那么这两个对象就不可能相等,如果超类的字段相等,就需要比较子类的实例字段是否相等。

    public class Manager extends Employee{
        private int bouns;
            public boolean equals(Object Obj){
            //这里调用super的equals方法主要比较两个对象是否属于同一个类
            if(!super.equals(obj)){return false}
            Manager other=(Manager) obj;
            return bonus==other.bouns
        }
    }

相等测试与继承

  • Java语言规范要求equals方法要有下面的特性:

    • 自反性:对于任何的非空引用x,x.equals(x)应该返回非空引用

    • 对称性:对于任何引用x和y,当且仅当x.equals(y)返回为true时,y.equals(x)返回为true

    • 传递性:对于任何引用x,y,z,如果x.equals(y),y.equals(z)都为true时,x.equals(z)返回为true

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

    • 对于任意非空的引用x,x.equals(null)应该返回false

  • 编写一个完美的equals方法的建议:

    • 显式参数命名obj,稍后还需要将它转换为另一个名为other变量

    • 检测this与obj是否相等

      if(this==obj) return true;
    • 检测obj是否为null,如果为null则返回false

      if(obj==null)return false;
    • 比较this与obj的类,如果equals的语义可以在子类中改变,就是用getClass检测:

      if(getClass()!=obj.getClass()) return false;
      • 如果所有的子类都有相同的相等性语义,可以使用instanceof检测

        if(!(obj instanceof ClassName)) return false;
    • 将obj强制转化为相应类类型的变量:

      ClassName other=(ClassName) obj;
    • 现在根据相等性概念的要求来比较字段。使用==比较基本类型,使用Objects.equals()比较对象字段,如果所有字段都匹配则返回true否则返回false

      return filed1=other.filed1
          && Objects.equals(filed2,other.filed2)
    • 若在子类中更新定义equals就要在其中包含一个super.equals(other)调用

    • 对于数组类型的字段,可以使用静态的Arrays.equals方法检测相应的数组元素是否相等,如果两个数组长度相同,并且在对应的位置上数据元素也相同将返回true

hashCode方法

  • 散列码是由对象导出的一个整型值

  • 散列码是没有规律的,两个不同的对象得到的散列码基本上不会相同

  • 字符串s和t有相同的散列码,是因为字符串的散列码是由内容导出的,而字符串sb和tb散列码不同,是因为在StringBuilder类中没有定义hashCode方法,而Object类的默认hashCode方法会从对象的存储地址得出散列码

  • 如果重新定义了equals方法,就必须为用户可能插入散列表的对象重新定义hashCode方法,当需要组合多个散列值时可以调用Objects.hash并提供所有这些参数,这个方法会对各个参数调用Object.hashCode,并组合这些散列值

    public int hashCode(){
        return Objects.hash(name.salsary,hireDay);
    }
  • equals和hashCode的定义必须相容:如果x.equals(y)返回true那么x.hashCode()和y.hashCode()返回相同的值

  • 如果存在数组类型的字段,那么可以使用静态的Arrays.hashCode方法计算一个散列码,这散列码由数组元素的散列码组成

toString方法

  • 返回表示对象值的一个字符串

  • 在Employee类中实现的toString方法

  • 可通过调用getClass().getName()获得类名的字符串,而不要将类名随意的编写到toString方法中

  • 这样的toString方法可以方便的被子类调用,设计子类的程序员也应该定义自己的toString方法,并加入子类的字段,如果超类使用了getClass().getName()那么子类只要调用super.toString()就可以了

  • 结果:

  • 在我们的代码中其实随处可见toString方法的主要原因:只要对象与一个字符串通过操作符“+”连接起来,Java编译器就会自动的调用toString方法来获得这个对象的字符串描述

    var p=new Point(10,20);
    String message="the current position is"+p

    实际上在这里调用了p.toString()

  • 其实可以不携程x.toString(),可以写成“ ”+x

  • 数组的打印:Arrays.toString()

  • 多维数组的打印:Arrays.deepToString

   参考书籍:Java核心技术 卷1(原书第11版)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Iron_Sp-man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值