2、Object

java.lang.Object

registerNatives()

native方法,让程序主动将本地方法链接到调用方,当Java程序需要调用本地方法时就可以直接调用,而不需要虚拟机再去定位并链接。

getClass()

getClass()方法返回当前运行时的类Class,即当前调用getClass()方法的对象对应的Class(字节码)实例。

clone()

clone()方法用于克隆当前对象,克隆分为浅克隆和深克隆。Object类中的clone()方法是浅克隆对象。

浅克隆

就是复制值一份,然后赋值给克隆出来的对象,所以当浅克隆基本数据类型时,那么可以实现真正意义上的克隆,但是当浅克隆引用数据类型时,那么就会出现复制地址引用一份,然后赋值给克隆对象,这种克隆仅仅只是克隆复制了一份地址引用,本质上这两个对象操作的还是同一块内存,所以达不到真正意义上的克隆对象。

实现深克隆

所以一般需要实现Cloneable接口,并重写clone()方法,当复制的属性是引用数据类型时,进行递归克隆(基本数据类型直接复制一份,引用数据类型递归调用clone()方法),重写完clone()方法才实现真正意义上的克隆。

equals()

==和equals()的区别
  1. ==,是一个比较运算符,既可以比较基本类型也可以比较引用类型。对于基本类型就是比较,对于引用类型就是比较内存地址
  2. equals()的话,它是属于java.lang.Object类里面的方法,如果某个类的equals()没有重写,那么和使用==比较的结果一样;我们可以看到String等类的equals()方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals()是比较值的错误观点。
  3. 具体要看自定义类里有没有重写Object的equals()方法来判断。
  4. 通常情况下,重写equals()方法,会比较类中的相应属性是否都相等。

hashCode()

什么是HashCode

哈希码(HashCode),并不是完全唯一的,它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。

HashCode的作用

如果在一个包含很多元素的集合中,查找一个元素,那么使用equals()方法挨个比较,那么会非常的慢。所以引入了哈希算法,哈希算法可以根据元素的某些特征(属性),计算出哈希值(散列值),相同哈希值的作为一组,也就是哈希桶,这个桶里面放着的都是哈希值相同元素。在查找元素的时候,可以很快的确定哈希值,从而找到哈希桶,并且在桶里面找到这个元素。

在java中,例如HashtableHashSetHashMap底层使用了数组+链表的基本存储结构,其中数组存储的就是HashCode并且这个HashCode指向一个链表(类似于哈希桶),链表里面存储的都是HashCode相同的元素

当自定义类没重写hashCode()时,哈希值是根据对象在内存中的地址生成的,所以,hashCode()常会和equals()方法同时重写,确保相等的两个对象拥有相等的hashCode

重写hashCode()与equals()

public class Student {

    private String name;

    private int age;

    @Override
    public boolean equals(Object o) {
        // 首先判断两个实例地址是否相同,同地址肯定是同一元素
        if (this == o) return true;
        // 判断元素是否为null,并且判断两个实例是否属于同一类
        if (o == null || getClass() != o.getClass()) return false;
        // 依次比较每一个属性是否相等
        Student student = (Student) o;
        return age == student.age && name.equals(student.name);
    }

    @Override
    public int hashCode() {
        // 调用Objects工具类的方法,计算多个属性共同的HashCode
        return Objects.hash(name, age);
    }
}

重写equals和hashCode方法

public class User {
    public String id;
    public String name;
    public int age;
    @Override
    public boolean equals(Object obj) {
        if(this == obj){
            return true;//地址相等
        }
        if(obj == null){
            return false;//非空性检查
        }
        if(obj instanceof User){
            User other = (User) obj;
            //需要比较的字段相等,则这两个对象相等
            if(this.name.equals(other.name) && this.age == other.age){
                return true;
            }
        }
        return false;
    }
    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + (name == null ? 0 : name.hashCode());
        result = 31 * result + (age == null ? 0 : age.hashCode());
        return result;
    }
}

toString()

获取实例信息,当使用System.out.println()方法打印一个实例的时候,默认调用的就是toString()方法,toString()如果没有重写,默认实现如下

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

notify()

用于唤醒因线程同步进入阻塞状态的任意一个线程

notifyAll()

用于唤醒因线程同步进入阻塞状态的所有线程

wait(timeout)

native方法,可以让当前正在执行的线程进入阻塞状态,直到其他线程调用notify()或者notifyAll()方法来唤醒这个线程,或者当过了参数timeout毫秒之后,自动从阻塞状态进入就绪状态

wait()

实际上就是wait(0),也就是阻塞后不会自动进入就绪状态,必须由其他线程调用notify()或者notifyAll()方法唤醒

public final void wait() throws InterruptedException {
   wait(0);
}

wait(timeout, nanos)

wait(timeout)更精细,支持0-999999的纳秒

finalize()

当垃圾回收机制(Garbage Collection)确认了一个对象没有被引用时,那么垃圾回收机制就会回收这个对象,并在回收的前一刻这个对象调用finalize()方法,这类似C++中的析构函数

java.util.Objects

Objects是jdk1.7添加的一个工具类,进行一些常用的检查操作。

equals(a,b)

可以不用考虑空指针异常,比较两个元素

public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}

deepEquals(a,b)

主要用于比较数组的所有元素是否相等

isNull(a)

判断元素是否为null

nonNull(a)

判断元素是否不为null

requireNonNull(obj)

检查元素是否为null,如果为null,则会抛出空指针异常;否则返回元素

requireNonNull(obj,message)

检查元素是否为null,如果为null,则会抛出空指针异常(自定义异常消息);否则返回元素

requireNonNullElse(obj,defaultObj)

检查obj是否为null,如果不为null则返回obj;如果为null,则返回defaultObj

hash(Object ... val)

为一系列的输入值生成哈希码,该方法的参数是可变参数。

toString(Object o)

返回指定对象的字符串形式。如果参数为null,则返回字符串"null"