Java Object类

1、概述

Object类是Java中所有类的超类,可以使用Object类型的变量来引用任何类型的对象。在Java中,只有基本类型不是对象,除此之外,所有的数组类型,不管是对象数组还是基本类型数组,都扩展了Object类。

2、equals方法

Object类中的equals方法用于检测一个对象是否等于另一个对象,这个方法将判断两个对象状态的相等性。由于任何类都继承自Object,而Object类中的equals方法仅仅用来判断两个对象是否具有相同的引用,所以在自定义类中,需要自己实现相应的equals方法,并在方法开始处调用超类的equals方法。

2.1 equals方法需要具备的特性

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

2.2 equals方法中如何判断两个对象是否属于同一个类

若使用instanceof关键字,则很容易会违反对称性。假设Manager类的超类是Employee类,Employee类中的equals方法这样定义到:

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

假设对象Employee e和Manager m具有相同属性,调用e.equals(m)返回了true,因为Manager instanceof Employee 为true。但是调用m.equals(e)却返回了false,因为Employee instanceof Manager为false。这就违反了对称性。
实际上,这两个对象所属的类虽然有继承关系,但是不应该相等。所以在判断类是否相等,应该使用getClass来判断:

if(e.getClass() != m.getClass())
	return false;

2.3 编写equals方法的建议

(1)显示参数命名为otherObject,在比较域值时,将其转换为对应类other变量;
(2)先检测是否具有相同引用

if(this == otherObject) return true;

(3)检测otherObject是否为null

if(otherObject == null) return false;

(4)比较this与otherObject是否属于同一类

if(getClass() != other.getClass()) return false;

当然,如果所有子类的equal具有同一语义,就应该使用instanceof来比较,这时候对于继承关系的类的对象,如果它们所有域值相同,认为它们也相同。
(5)将otherObject转换为相应类型变量,比较其基本域

ClassName other = (ClassName) otherObject
return xxx == xxx && xxxx == xxxx && ... 

3 hasCode方法

hasCode方法返回一个整型值散列码,散列码没有规律,但是两个不同的对象应该具有不同的散列码(非严格)。

3.1 hasCode与equals的关系

如果两个对象equal,那么其散列码一定要相同;反之如果两个对象不equal,不一定要求其散列码不相同,但通常是不相同的。

产生不同的散列码有助于优化哈希表性能,尽量避免哈希冲突,但是真正发生了哈希冲突,可以通过链式地址法,在同一个哈希地址建立一个链表将具有同样哈希地址的内容链接。

这就解释了散列码相同的对象也有可能是不equal的。

3.2 自定义hasCode函数

如果自定义了类却没有重写hasCode方法,默认调用Object中的hasCode方法,它返回的是对象的引用地址。
但是在重写equals方法和hasCode方法,必须确保其满足3.1中的条件。

4 toString方法

一般建议为自定义类都重写一个toString()方法,一般遵循格式:类名+[field1=xx,filed2=xx,…]。

5 实例

Java核心技术卷1第10版 程序清单5-8 5-9 5-10

public class Employee {
    private String name;
    private double salary;
    private LocalDate hireDay;

    public Employee(String name,double salary,int year,int month,int day)
    {
        this.name = name;
        this.salary = salary;
        hireDay = LocalDate.of(year,month,day);
    }

    public String getName()
    {
        return name;
    }

    public double getSalary()
    {
        return salary;
    }

    public LocalDate getHireDay()
    {
        return hireDay;
    }

    public void raiseSalary(double byPercent)
    {
        double raise = salary * byPercent;
        salary += raise;
    }

    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);
    }

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

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


}
public class Manager extends Employee{

    private double bonus;

    public Manager(String name, double salary, int year, int month, int day)
    {
        super(name, salary, year, month, day);
        bonus = 0;
    }

    public void setBonus(double bonus)
    {
        this.bonus = bonus;
    }

    public double getBonus()
    {
        return bonus;
    }

    public boolean equals(Object otherObject)
    {
        if (!super.equals(otherObject))
            return false;

        Manager other = (Manager) otherObject;

        return bonus == other.bonus;
    }

    public int hasCode()
    {
        return super.hasCode() + 17 * new Double(bonus).hashCode();
    }

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

}
public class EqualsTest {
    public static void main(String[] args)
    {
        Employee alice1 = new Employee("Alice Adams",75000,1987,12,15);
        Employee alice2 = alice1;
        Employee alice3 = new Employee("Alice Adams",75000,1987,12,15);
        Employee bob = new Employee("Bob Brandson",50000,1989,10,1);


        System.out.println("alice1 == alice2: " + (alice1 == alice2));
        System.out.println("alice1 == alice3: " + (alice1 == alice3));
        System.out.println("alice1.equals(alice3): " + (alice1.equals(alice3)));
        System.out.println("alice1.equals(bob): " + (alice1.equals(bob)));
        System.out.println("bob.toString(): " + bob);

        Manager carl = new Manager("Carl Cracker",80000,1987,12,15);
        Manager boss = new Manager("Carl Cracker",80000,1987,12,15);
        boss.setBonus(5000);
        System.out.println("boss.toString(): " + boss);
        System.out.println("carl.equals(boss): " + carl.equals(boss));
        System.out.println("alice1.hasCode(): " + alice1.hasCode());
        System.out.println("alice3.hasCode(): " + alice3.hasCode());
        System.out.println("bob.hasCode(): " + bob.hasCode());
        System.out.println("carl.hasCode(): " + carl.hasCode());
        System.out.println("boss.hasCode(): " + boss.hasCode());

    }

}

结果

alice1 == alice2: true
alice1 == alice3: false
alice1.equals(alice3): true
alice1.equals(bob): false
bob.toString(): equals.Employee[name=Bob Brandson,salary=50000.0,hireDay=1989-10-01]
boss.toString(): equals.Manager[name=Carl Cracker,salary=80000.0,hireDay=1987-12-15][bonus=5000.0]
carl.equals(boss): false
alice1.hasCode(): -808853550
alice3.hasCode(): -808853550
bob.hasCode(): -624019882
carl.hasCode(): -341762419
boss.hasCode(): 931997325

Process finished with exit code 0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值