5.2 Object:所有类的超类

1、Object类是Java所有类的超类。如果没有明确指出一个类的超类,那么object就是这个类的超类,并且不需要显示的写出。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值