Java Object 类总结

531 阅读3分钟

java.lang.Object

public class Object {

    private static native void registerNatives();
    static {
        registerNatives();
    }

    // 返回对对象的Class对象的引用
    public final native Class<?> getClass();

    // 返回对象的哈希码(整数)值
    public native int hashCode();

    // 比较两个对象的相等性
    public boolean equals(Object obj) {
        return (this == obj);
    }

    // 创建对象的副本 需自定义
    // Object本身没有实现Cloneable接口,所以不重写clone方法并且进行调用的话会发生CloneNotSupportedException异常
    protected native Object clone() throws CloneNotSupportedException;

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

    // 通知所有位于等待池(WaitSet)中的线程对象进入锁池(EntryList)中竞争获取锁的机会
    public final native void notifyAll();

    // 随机通知一个线程对象进入锁池
    public final native void notify();
    
    // 使线程进入 Waiting 状态 (无限期等待,不会被分配 CPU 时间,需要被显示唤醒)
    public final void wait() throws InterruptedException {
        wait(0);
    }
    
    // 进入 Timed Waiting 状态,限期等待,到时自动唤醒
    public final native void wait(long timeout) throws InterruptedException;

    public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException("nanosecond timeout value out of range");
        }
        if (nanos > 0) {
            timeout++;
        }
        wait(timeout);
    }

    // 对象被销毁之前被垃圾收集器调用
    @Deprecated(since="9")
    protected void finalize() throws Throwable { }
}

finalize() @Deprecated

  • fnalize被设计成在对象被垃圾收集前调用,JVM要对它进行额外处理。
  • 无法保证fnalize什么时候执行,执行的是否符合预期,使用不当会影响性能,导致程序死锁、挂起等。
  • 我们要确保回收资源就是因为资源都是有限的,垃圾收集时间的不可预测,可能会极大加剧资源占用。fnalize本质上成为了快速回收的阻碍者,可能导致对象经过多个垃圾收集周期才能被回收。

代替方式

  • 用 java.lang.ref.Cleaner 来替换掉原有的 fnalize 实现
  • leaner 的实现利用了幻象引用(PhantomReference),这是一种常见的所谓 post-mortem 清理机制
  • 每个 Cleaner 的操作都是独立的,它有自己的运行线程,所以可以避免意外死锁等问题
  • 很多第三方库自己直接利用幻象引用定制资源收集,比如广泛使用的 MySQL JDBC driver 之一的 mysql-connector-j

protected native Object clone()

  • 创建对象的副本 需自定义
  • Object 本身没有实现 Cloneable 接口,protected 方法,重写后才能被调用
  • 需实现implements Cloneable,否则会 throw CloneNotSupportedException

实现示例

public class Product implements Cloneable {
    private int number;
    private Date date;
    
    // constructor / getter / setter
    
    public Object clone() throw CloneNotSupportedException {
        Product p = null;
        // 完成基本类型的复制
        p = (Product) super.clone();
		// 完成引用类型的复制
        p.date = (Date) this.getDate().clone();
        return p;
    }
}

equals() hashCode()

利用 Java7+ Objects 中方法

public class Student {
    private int id;
    private String name;
    private String city;
    
    // constructor / getter / setter
    
    // Objects method java7+
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return id == student.id &&
                Objects.equals(name, student.name) &&
                Objects.equals(city, student.city);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id, name, city);
    }
}

自定义( idea 生成示例)

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Student student = (Filter) o;

    if (id != student.id) return false;
    if (name != null ? !name.equals(student.name) : student.name != null) return false;
    return city != null ? city.equals(student.city) : student.city == null;
}

@Override
public int hashCode() {
    int result = id;
    result = 31 * result + (name != null ? name.hashCode() : 0);
    result = 31 * result + (city != null ? city.hashCode() : 0);
    return result;
}