zoukankan      html  css  js  c++  java
  • Java 面向对象:Object 类

    禁止码迷,布布扣,豌豆代理,码农教程,爱码网等第三方爬虫网站爬取!

    所有类的超类

    Object 类是 Java 中所有类的超类,Java 中的每个类都是 Object 类的子类。因此可以使用 object 类型的变量引用任何类型的变量,但是 Object 类型的变量只能作为各种值的泛型容器,想要操作该对象还是需要强制类型转换。

    Object obj = new Employee("Alice Adams", 75000);
    Employee e = (Employee) obj;
    

    在 Java 中基本类型不是对象,而所有数组类型都是基于 Object 类实现的。这点还是很特别的,因为 C++ 没有所有类的根类,而 Python 中的所有数据类型都是对象。

    equals 方法

    同类判断

    equals 方法可以检测一个对象是否等于另一个对象,在 Object 类中的判断方式是判断 2 个对象的引用是否相等。但是在很多情况下我们不关心特们的引用是否相等,而是关系各个状态字段是否相等。因此在基础 equals 方法时,我们经常需要针对状态来进行覆盖。
    首先先看看 getClass() 方法,该方法可以返回对象所属的类。使用 getClass() 方法进行判断是可行的,因为当 2 个对象属于同一个类时才有可能相等。接着程序就需要对字段的各状态进行判断:

    private String name;
    private double salary;
    private LocalDate hireDay;
    
    public boolean equals(Object otherObject){
          if (this == otherObject)      //判断引用是否相等
                return true;
    
          if (otherObject == null)      //判空
                return false;
    
          if (getClass() != otherObject.getClass())      //判断是否是相同的类 
                return false;
    
          Employee other = (Employee) otherObject;      //强制类型转换
          return Objects.equals(name, other.name)      //比较各个字段值
                && salary == other.salary 
                && Objects.equals(hireDay, other.hireDay);
    }
    

    当子类覆盖了超类的 equals 方法时,因为超类的 equals 方法可能是私有方法,因此要先调用超类的 equals 方法。

    private double bonus;
    
    public boolean equals(Object otherObject){
          if (!super.equals(otherObject)) 
                return false;
    
          Manager other = (Manager) otherObject;      
          return bonus == other.bonus;
    }
    

    非同类判断

    如果显式参数和隐式参数不是同一个类,equals 使用什么方案判断更为合适?首先先谈一下 instanceof 关键字,它可以测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。

    if(!(otherObject instanceof Employee))
          return false;
    

    写代码时要怎么选择 instanceof 关键字和 getClass() 方法呢?equals 的设计需要考虑 2 种情形:

    1. 子类可以有自己的相等性概念,使用 getClass() 方法检测;
    2. 超类决定相等性概念,选择 instanceof 关键字检测。

    equals 方法设计

    因此设计一个 equals 方法可以参考以下几点:

    1. 显式参数命名为 otherObject,比较时用强制类型转换为另一个 other 变量;
    2. 检测 this 和 otherObject 是否相等;
    3. 检测 otherObject 是否是 null;
    4. 比较 this 与 otherObject 的类是否相同;
    5. 将 otherObject 强制类型转换为相应的类类型变量,比较各个字段。

    hashCode 方法

    散列码是由对象导出的一个整数值,不同的对象的散列码不同,Object 方法会根据存储地址的不同,为每一个对象提供一个散列码。例如 String 计算散列码的代码:

    int hash = 0;
    for(int i = 0; i < length(); i++)
          hash = 31 * hash + charAt(i);
    

    hashCode 方法定义在 Object,可以返回对象的散列值。当 equals 方法被覆盖时,hashCode 方法也要随之修改,因为 “x.equals(y)” 判断为 true 的 2 个对象,执行 “x.hashCode() == y.hashCode()” 也要为真。当需要组合多个散列值时,使用 Object.hash() 方法是不错的选择。

    public int hashCode(){
          return Objects.hash(name, salary, hireDay); 
    }
    

    toString 方法

    toString 方法可以返回表示对象值的字符串,常见的表示是“类名+字段值”。例如:

    public String toString(){
          return getClass().getName() 
                + "[name=" + name 
                + ",salary=" + salary 
                + ",hireDay=" + hireDay + "]";
    }
    

    当子类继承超类的 toString 方法时,可以用 super 关键字调用超类的 toString 方法。

    public String toString(){
          return super.toString() + "[bonus=" + bonus + "]";
    }
    

    当对象和一个字符串用 “+” 运算符连接时,toString 方法就会被自动调用。toString 方法可以放映类中各个状态的变化,因此很适合用于调试。

    变参方法

    注意到我们熟悉的 printf 方法,这个函数能够接收多个参数,它的方法定义如下所示。

    public class PrintStream{
          public PrintStream printf(String fmt, Object… args){
                return format(fmt, args);
          }
    }
    

    使用 “…” 表示方法可以接受任意数量的对象,而这些对象可以被组织为一个 Object[] 数组来使用。例如这个方法可以比较多个数字的大小:

    public static double max(double… values){
          double largest = values[0];
          for(double v:values){
                if(v > largest)
                      largest = v;
          }
          return largest;
    }
    

    参考资料

    《Java 核心技术 卷Ⅰ》,[美]Cay S.Horstmann 著,林琪 苏钰涵 等译,机械工业出版社

  • 相关阅读:
    python学习笔记(1)
    一些有趣的使用function
    axios构建请求池处理全局loading状态&&axios避免重复请求
    axios构建缓存池存储基础数据
    文件下载方法
    关于 JS this
    前端 JS 获取 Image 图像 宽高 尺寸
    Html CSS transform matrix3d 3D转场特效
    Github 持续化集成 工作流 Npm包自动化发布
    远程 Linux(Ubuntu 18)添加字体
  • 原文地址:https://www.cnblogs.com/linfangnan/p/13418477.html
Copyright © 2011-2022 走看看