Java万物皆对象Object类

一.概述

上一篇讲解了Java继承与多态的基本使用。链接:Java继承与多态
这篇讲解Object类,前面讲了Java是完全面向对象的,所以在Java的世界里任何事物都可以理解为对象,Object就是最终的类——对象类。他定义了对象最基本的固有方法。所有的类都会继承自Object类中的方法。下面说几个比较常用的方法,还有几个是线程方面的方法,后期讲到线程的时候会讲到。

二.Object类

1.equals方法

Object的equals方法用于检测一个对象是否等于另一个对象。在Object类中的这个方法,是判断两个对象是否具有相同的引用。如果两个对象的引用是相等的,它们就是相等的。但是对于我们想要比较的对象是否相等的原则并不是根据地址,往往通过对象的状态,如果两个对象的状态相同,就认为这两个对象相等。

import java.time.LocalDate;
import java.util.Objects;

/**
 * 员工类
 */
public class Employee {
	private String name;
	private double salary;
	private LocalDate hireDay;
	
	/**
	 * 覆盖Object类中的equals方法
	 * @param obj
	 * @return
	 */
	@Override
	public boolean equals(Object obj) {
		// 检测当前对象和obj是否引用同一个对象,实际比较的是内存地址。
		if (this == obj) {
			return true;
		}
		// 如果obj为null,对应第五条特性
		if (obj == null) {
			return false;
		}
		// 因为子类也要决定是否相等的概念所以使用getClass()方法
		if (getClass() != obj.getClass()) {
			return false;
		}
		// 进行强制类型转换调用子类的特有方法
		Employee employee = (Employee)obj;
		return Objects.equals(name,employee.name) 
					&& salary == employee.salary 
					&& Objects.equals(hireDay,employee.hireDay);
	}
	//此处省略getter和setter方法...
}
/**
 * 子类覆盖父类的equals
 */
public class Manager extends Employee{
	
	private double bonus;

	/**
	 * 子类继承父类并覆盖父类的equals方法
	 * @param obj
	 * @return
	 */
	@Override
	public boolean equals(Object obj) {
		if (!super.equals(obj)) {
			return false;
		}
		Manager manager = (Manager) obj;
		return bonus == manager.bonus;
	}
	// 省略其他...
}

Java语言规范要求equals方法具有下面的特性:
(1)自反性:对于任何非空引用x,x.equals(x)应该返回true
(2)对称性:对于任何引用x和y,x.equals(y),返回true,那么y.equals(x)也应该返回true。
(3)传递性:对于任何引用x,y,z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true。
(4)一致性:如果x和y引用的对象没有发生变化,反复调用x.equals(y)应该返回同样的结果。
(5)对于任意非空引用x,x.equals(null)应该返回false。

但是以上特性都是针对的同一个类型而言,当类型不一样的时候又是什么样子呢??
当一个Employee类型对象和Manager类型对象具有相同的状态时,而Employee类重写的equals方法用instanceof进行了检测,则返回true,那么利用对称性则意味着Manager类调用equals方法也应该返回true。但是Manager类中有自己的实例域,无法比较特有的信息,所以即使判断了类型也无法进行特有的实例域进行比较。比如两个特有的属性不同也认为是相同的对象是不合适的。所以往往instanceof并不是完美的。
记住以下两个要点:

  • 如果子类能够拥有自己的相等概念,则对称性需求将强制采用getClass()方法进行检测。
  • 如果由父类决定相等的概念,那么就可以使用instanceof进行检测,这样可以在不同的子类的对象之间进行相等的比较。

2.hashCode方法

散列码(hash code)是由对象导出的一个整型值。因为此方法是在Object类中,所以每个对象都有自己的hashCode值,其值为对象的地址。

	/**
	 * 覆盖父类的hashCode方法
	 * @return
	 */
	@Override
	public int hashCode() {
		// Objects.hash()方法将每个参数调用hashCode值
		return Objects.hash(name,salary,hireDay);
	}
/**
	 * 覆盖父类的hashCode方法
	 * @return
	 */
	@Override
	public int hashCode() {
		return super.hashCode() + 17 * new Double(bonus).hashCode();
	}

3.equals和hashCode的关系

应该都听过重写equals就要重写hashcode,这是为什么呢??
如果只是比较两个对象相比较,那么重写equals方法就可以了,但是后面讲到的Hash类型的集合是不可以的,他们的判断逻辑是先判断放入集合中的对象hash值是否相等,如果相等,在进行equals方法的判断,因为每个对象获取的hashcode值不一定不同(由于hash算法的原因),所以hashCode值往往是不可靠的,我们通过重新写equals方法来进行比较。更深层次可以参考hash类型的集合源码以及hash算法。
测试结果demo:

/**
 * 测试equals方法
 */
public class EqualsDemo {
	public static void main(String[] args) {
		// 测试equals方法
		Employee alice1 = new Employee("Alice", 1000, 1999, 10, 1);
		Employee alice2 = alice1;
		Employee alice3 = new Employee("Alice", 1000, 1999, 10, 1);
		Employee bob = new Employee("Bob", 2000, 2000, 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));
		//测试hashcode方法
		Manager carl = new Manager("Carl", 2000, 1999, 1, 1, 12);
		Manager boss = new Manager("Carl", 2000, 1999, 1, 1, 12);
		boss.setBonus(5000);
		System.out.println("carl.equals(boss):" + carl.equals(boss));
		System.out.println("alice1.hashCode():" + alice1.hashCode());
		System.out.println("alice3.hashCode():" + alice3.hashCode());
		System.out.println("bob.hashCode():" + bob.hashCode());
		System.out.println("carl.hashCode():" + carl.hashCode());

	}
}

三.结束语

还有原来toSting方法,也是Object类的方法,这个方法原本是用来打印对象所属的类名和散列码,这个信息对我们俩说毫无意义,随意要重写toString方法来进行显示对象的状态。
下一篇讲包装类以及枚举类的基本使用
有些可能我理解的不够深刻,大家如果觉得我说的不够详细可以参考我的推荐书,详细的看一下。欢迎大家评论。第一时间我会回复大家。谢谢!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值