java.lang.Object类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。在对象实例化的时候,最终找的父类就是Object。

1. toString方法

  • public String toString():返回该对象的字符串表示。

toString方法返回该对象的字符串表示,其实该字符串内容就是对象的类型+@+内存地址值。
由于toString方法返回的结果是内存地址,而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它。

  1. public class Person {
  2. private String name;
  3. private int age;
  4. @Override
  5. public String toString() {
  6. return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
  7. }
  8. // 省略构造器与Getter Setter
  9. }

2. equals方法

  • public boolean equals(Object obj):指示其他某个对象是否与此对象“相等”。

Object类中默认进行==运算符的对象地址比较,只要不是同一个对象,结果必然为false。

重写equals(Object obj)的模板:

  1. @Override
  2. public boolean equals(Object obj) {
  3. //1. 是否是同一个对象
  4. if(this == obj){
  5. return true;
  6. }
  7. //2. 是否为空
  8. //3. 是否是要比较的类的对象(防止强制转型失败)
  9. if((obj==null) || (obj instanceOf Student){
  10. return false;
  11. }
  12. //4. 返回判断结果
  13. return this.name.equals((Student)anObject.name); //不要忘了做向下转型!
  14. }

当比较基本类型变量时,使用==; 当比较引用类型变量时,使用equals().

3. hashCode方法

  • public int hashCode() : 返回对象的哈希值,普通的十进制整数。默认情况下如果没有重写hashCode()方法,每个对象运行hashCode()的结果都不同。

    如果一个类重写了equals()方法,则必须重写hashCode()方法。2个对象的equals()方法返回true的话,其hashCode()必须返回相同的值。否则对于HashSet, HashMap, HashTable等基于hash值的类就会出现问题。

    hash值是如何被计算出来的呢?

    image.png
  1. 看一下String的hashCode: String是以每个字母的值来计算hash的,因此当字母相同时,String也是equals。

    1. public int hashCode() {
    2. int h = hash;
    3. if (h == 0 && value.length > 0) {
    4. char val[] = value;
    5. for (int i = 0; i < value.length; i++) {
    6. h = 31 * h + val[i];
    7. }
    8. hash = h;
    9. }
    10. return h;
    11. }

    Objects.hash(Object…o)

  2. 我们再看一下一般应该如何定义一个hashCode()方法:Objects.hash(o…objs)

    1. public class Employee {
    2. private String name;
    3. private String phone;
    4. private String address;
    5. @Override
    6. public boolean equals(Object obj) {
    7. if (obj instanceof String) {
    8. Employee other = (Employee) obj;
    9. return (this.name.equals(other.name) && this.phone.equals(phone));
    10. }
    11. return false;
    12. }
    13. @Override
    14. public int hashCode() {
    15. return 7*name.hashCode() + 11*phone.hashCode();
    16. }
    17. public int hashCode2() {
    18. return 7* Objects.hashCode(name) + 11* Objects.hashCode(phone);
    19. }
    20. public int hashCode3() {
    21. return Objects.hash(name,phone);
    22. }
    23. }

    我们假设当name和phone相同时,则认为这2个对象是equals的。
    hashCode()方法是传统的方法,hashCode2()和hashCode3()这2种办法都是JDK7以后支持的,可以简化代码,而且可以避免name为空之类的情形,尤其第3种。
    如不需要严格控制hash值,则使用第3种。如要控制hash值,则用第2种。

    Objects的hash()和hashCode()比较

    1. public class HelloWord{
    2. public static void main(String[] args) {
    3. System.out.println("a".hashCode());
    4. System.out.println(Objects.hashCode("a"));
    5. System.out.println(Objects.hash("a"));
    6. }
    7. }
    8. 输出结果:97 97 128

    由此可见:前两个都是直接计算a的hashCode()编码的,而第三个确实得出不一样的结果.
    Objects类中的hash()函数是这样定义的

    1. public static int hash(Object... values) {
    2. return Arrays.hashCode(values);
    3. }

    这里调用Arrays类的hashCode()函数

    1. public static int hashCode(Object a[]) {
    2. if (a == null){
    3. return 0;
    4. }
    5. int result = 1;
    6. for (Object element : a){
    7. result = 31 * result + (element == null ? 0 : element.hashCode());
    8. }
    9. return result;
    10. }

4. hashCode和equals的面试题

  1. 两个对象 Person p1 p2
  2. 问题:如果两个对象的哈希值相同 p1.hashCode()==p2.hashCode()
  3. 两个对象的equals一定返回true p1.equals(p2) 一定是true吗?
  4. 正确答案:不一定
  5. 问题:如果两个对象的equals方法返回true,p1.equals(p2)==true
  6. 两个对象的哈希值一定相同吗
  7. 正确答案: 一定

在 Java 应用程序执行期间:
1.如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
2.如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不要求一定生成不同的整数结果。