一、Object对象简介

Object类是java.lang包下的核心类,是所有类的父类
所有的Java对象都隐式地继承了Object对象(不用写extends继承)
所有的对象都拥有Object默认的方法

那么先来看一看Object都有些什么方法:

java Object 对象获取 java获取object对象的值_浅克隆


registerNatives() 底层实现

clone() 克隆(复制)

equals() 对象值比较

finalize() 垃圾回收前调用的方法

getClass() 返回字节码文件对象class

hashCode() 对象的hash值

notify() 唤醒线程

notifyAll() 唤醒全部线程

toString() 获取对象的信息

wait() 线程等待


二、equals和hashCode方法

equals()比较对象的地址是否相等,如果子类重写,则比较对象的内容是否相等

public native int hashCode();
public boolean equals(Object obj) {
	return (this == obj);
}

hashCode()native方法底层实现
equals()直接==判断是否相等

equals()方法默认比较对象的地址,使用==等值运算符

equals()方法的默认原则:

  • 自反性:x.equals(x)必须返回true
  • 一致性:只要对象没有被修改,那么多次调用还是返回对应的结果
  • 传递性:x.equals(y)y.equals(z)都返回true,那么x.equals(z)也返回true
  • 对称性:x.equals(y)y.equals(x)结果应该是相等的
  • 任何情况下x.equals(null),都会返回false

hashCode()方法对底层是散列表的对象有提升性能的功能


1、equals和hashCode方法重写

equals()方法默认比较对象的地址,使用的是==运算符

重写equals()方法,就必须重写hashCode()方法,以保证相同的对象返回相同的hash值,不同的对象返回不同的hash值

为什么要重写equals方法?

equals是Object中的方法,其源码如下:

java Object 对象获取 java获取object对象的值_浅克隆_02


可以看出,equals默认使用==来比较,而==对于基本数据类型,比较的是值,对于引用数据类型,比较的是内存地址。

根据hashCode的规范,我们重写了equals()就必须重写hashCode()


为什么要重写hashCode()?

hashCode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable 类来存储数据时,都会根据存储对象的 hashCode 值来进行判断是否相同。

由于Object的hashCode返回的是对象的hash值,所以即使equals返回TRUE,集合也可能判定两个对象不等,所以必须重写hashCode方法,以保证当equals返回TRUE时,hashCode也返回Ture,这样才能使得集合中存放的对象唯一


两个对象用equals方法比较结果为true,他们的hashcode值相同么?

不一定相同。正常情况下,因为equals()方法比较的就是对象在内存中的值,如果值相同,那么Hashcode值也应该相同。但是如果不重写hashcode方法,就会出现不相等的情况。

2、String实现的equals和hashCode方法

String已经实现了equals和hashCode方法

所以,我们可以直接使用String.equals()来判断两个字符串是否相等

java Object 对象获取 java获取object对象的值_浅克隆_03


java Object 对象获取 java获取object对象的值_java_04

三、toString方法

在实际开发中,通常希望对象的toString()方法返回的不仅仅是基本信息,而是一些特有的信息,这时重写Object的toString()方法便可以实现。

toString()以文本的方式来表示一个对象,可以根据实际需要重写toString()来编写打印结果

@Override
    public String toString() {
        return "Student{" +
                "姓名:'" + name + '\'' +
                ", 成绩:'" + grades + '\'' +
                '}';
    }

java Object 对象获取 java获取object对象的值_java object类 获取长度_05


四、clone方法

java Object 对象获取 java获取object对象的值_编程语言_06

  • clone方法用于对象的克隆,一般克隆出的对象是独立的(与原有的对象分开)
  • 深层克隆指的是该对象的成员变量(如果是可变引用)都应该克隆一份,浅克隆指的是成员变量没有被克隆一份

java Object 对象获取 java获取object对象的值_java object类 获取长度_07


浅克隆:基本数据类型属性完全重新创建,引用类型属性依然共用的克隆

java Object 对象获取 java获取object对象的值_编程语言_08

深克隆:所有类型属性都完全重新创建

java Object 对象获取 java获取object对象的值_浅克隆_09


如何使用克隆?

无论是深克隆还是浅克隆:

  • 克隆的对象要实现Cloneable接口
  • 重写克隆方法,最好修饰成public

clone()Objectprotected方法,他不是public方法,一个类不显示地重写clone(),其它类就不能直接去调用该类实例的 clone() 方法

应该注意的是, clone() ⽅法并不是 Cloneable 接⼝的⽅法,而是 Object 的一个 protected ⽅法。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() ⽅法,就会抛出CloneNotSupportedException


浅克隆:仅仅克隆了Person对象,而name没有克隆!

public class Person implements Cloneable {

    // 可变的成员变量
    private String name;

    @Override
    public Object clone() throws CloneNotSupportedException {

        return super.clone();
    }
}

深克隆:不仅克隆了Person对象,也克隆了name成员变量

public class Person implements Cloneable {

    // 可变的成员变量
    public String name;

    @Override
    public Object clone() throws CloneNotSupportedException {

        // 克隆Person对象
        Person person = (Person) super.clone();

        // 将可变的成员变量也克隆
        person.name = (String) name.clone();

        // 返回克隆的对象
        return person;
    }
}