<CoreJava> 5.2 Object:所有类的超类
1、Object类是Java所有类的超类。如果没有明确指出一个类的超类,那么object就是这个类的超类,并且不需要显示的写出。
Employee.java:
Manager.java:
2、Object类型的变量可以引用任何类型的对象:
Object obj = new Employee("vincent", 100000);
如果要对内容进行操作必须要类型转换:
Employee e = (Employee)obj;
3、在Java中只有基本数据类型(即数值,布尔值,字符)不是对象。所有的数组类型都是Object的扩展类。
5.2.1 Equals方法
1、判断两个对象是否有相同的引用。如果两个对象的状态相同,就认为二者相等。
例如:两个雇员对象的姓名,薪水,雇佣日期都一样,就认为他们相等(实际中只要比较他们在数据库中的ID更有效):
class Employee {
...
public boolean equals(Object otherObject) {
if(this == otherObject) return true;
if(otherObject == null) return false;
if(this.getClass() != otherObject.getClass())
return false;
Employee other = (Employee)otherObject;
return name.equals(other.name)
&& salary == other.salary
&& hireDay == other.hireDay);
}
}
gerCalss方法将返回一个对象所属的类。
2、在子类中使用equals方法时,先调用超类中的equals方法。超类中的equals为false那么子类一定为false。如果超类中的域都相等就要比较子类中的实例域。
5.2.2相等测试与继承
1、Java要求equals具有以下特性:
1)自反性:对任何非空引用x,x.equals(x)的返回值为true;
2)对称性:对任何引用x和y,当且仅当x.equals(y)为true, y.equals(x)也为true;
3)一致性:如果x和y的引用没有改变,那么反复调用x.equals(y)的返回值相同;
4)传递性:对于任何引用x、y和z,如果:x.equals(y)为true,y.equals(z)也为true,那么x.equals(z)一定为true;
5)对任意非空引用x,x.equals(null)返回false。
2、编写一个完美equals的建议:
1)显式参数命名为otherObject,然后将它转换成other变量;
2)检测this和otherObject是否引用同一个对象:
if (this == otherObject) return true;
3)检测otherObject是否为null:
if(otherObject == null) return false;
4)比较this与otherObject是否属于同一个类:
if(this.getCalss() != otherObject.getCalss()) return false;
5)将otherObject转换成相应类的类型变量:
ClassName other = (ClassName) otherObject
6)开始对所有需要比较的域进行比较,使用“==”比较基本数据类型,使用“equals“比较对象域。
5.2.4 ToString方法
toString方法是一种非常有用的调试工具。强烈建议为每一个自定义类加上toString方法。
源代码:例5-3的程序实现了Employee类和Manager类的equals,hashcode和toString方法:
EqualsTest.java:
- package com.vincent.corejava.equalstest;
- public class EqualsTest {
- public static void main(String[] args) {
- Employee alice1 = new Employee("Alice Adams", 7500, 1987, 12, 15);
- Employee alice2 = alice1;
- Employee alice3 = new Employee("Alice Adams", 7500, 1987, 12, 15);
- Employee bob = new Employee("Bob", 5000, 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", 8000, 1987, 12, 15);
- Manager boss = new Manager("Carl", 8000, 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.hashCode(): " + alice1.hashCode());
- System.out.println("alice3.hashCode(): " + alice3.hashCode());
- }
- }
Employee.java:
- package com.vincent.corejava.equalstest;
- import java.util.Date;
- import java.util.GregorianCalendar;
- class Employee {
- private String name;
- private double salary;
- private Date hireDay;
- public Employee(String aName, double aSalary, int year, int month, int day) {
- name = aName;
- salary = aSalary;
- GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
- hireDay = calendar.getTime();
- }
- public String getName() {
- return name;
- }
- public double getSalary() {
- return salary;
- }
- public Date getHireDay() {
- return hireDay;
- }
- public void raiseSalary(double byPercent) {
- double raise = salary * byPercent / 100;
- salary += raise;
- }
- public boolean equals(Object otherObject) {
- //检测二者是否引用同一个对象
- if (this == otherObject) return true;
- //检测otherObject是否为空引用
- if (otherObject == null) return false;
- //检测二者是否属于同一个类
- if (this.getClass() != otherObject.getClass()) return false;
- Employee other = (Employee)otherObject;
- return name.equals(other.name)
- && salary == other.salary
- && hireDay.equals(other.hireDay);
- }
- public int hashCode() {
- return
- 7 * name.hashCode()
- + 11 * new Double(salary).hashCode()
- + 13 * hireDay.hashCode();
- }
- public String toString() {
- return getClass().getName() +
- "[name= " + name
- + ", salary= " + salary
- + ", hireDay= " + hireDay
- +"]";
- }
- }
Manager.java:
- package com.vincent.corejava.equalstest;
- public class Manager extends Employee{
- private double bonus;
- public Manager(String aName, double aSalary, int year, int month, int day) {
- super(aName, aSalary, year, month, day);
- bonus = 0;
- }
- public double getSalary() {
- double baseSalary = super.getSalary();
- return baseSalary +bonus;
- }
- public void setBonus(double aBonus) {
- bonus = aBonus;
- }
- public boolean equals(Object otherObject) {
- if (!super.equals(otherObject)) return false;
- Manager other = (Manager)otherObject;
- return bonus == other.bonus;
- }
- public int hashCode() {
- return super.hashCode() + 17 * new Double(bonus).hashCode();
- }
- public String toString() {
- return super.toString() + "[bonus= " + bonus + "]";
- }
- }
运行结果:
alice1 == alice2: true
alice1 == alice3: false
alice1.equals(alice3): true
alice1.equals(bob): false
bob.toString(): com.vincent.corejava.equalstest.Employee[name= Bob, salary= 5000.0, hireDay= Sun Oct 01 00:00:00 CST 1989]
boss.toString(): com.vincent.corejava.equalstest.Manager[name= Carl, salary= 8000.0, hireDay= Tue Dec 15 00:00:00 CST 1987][bonus= 5000.0]
carl.equals(boss): false
alice1.hashCode(): 339562723
alice3.hashCode(): 339562723