美文网首页
Object类简介

Object类简介

作者: pittiw | 来源:发表于2020-02-06 20:15 被阅读0次

    1 hashCode

    hashCode的一般约定为:

    1. 同一个程序中多次调用返回相同的值。不会为equals方法比较对象提供信息。
    2. 如果两个对象equals结果为true,那么hashCode的结果也相等。
    3. 如果两个对象equals结果为falsehashCode结果可能相等也可能不相等。保证不相等对象的哈希值不同,有助于提高哈希表的性能。

    2 equals

    用于比较是否和传入对象相等。
    equals的等价条件是:

    1. 自反性。任何非null引用x有,x.equals(x)返回true
    2. 对称性。任何非null引用xy有,x.equals(y)返回ture当且仅当y.equals(x)也返回`true。
    3. 传递性。任何非null引用xyz有,如果x.equals(y)y.equals(z),那么x.equals(z)
    4. 一致性。任何非null引用xy,如果没有修改对象,那么多次调用x.equals(y)返回的结果是一致的。
    5. 任何非null引用。x.equals(null)false

    Object类对象比较特别,x.equals(y)true当且仅当x == ytrue

    在重写equals方法时,需要重写hashCode方法。为的是保证hashCode的第1条特性能够成立。

    3 clone

    克隆结果的特性

    1. x.clone != xtrue
    2. x.clone.getClass() == x.getClass()true,如果拷贝的过程中,调用了super.clone(除Object类之外)。
    3. x.clone.equals(x)true,如果重写了equals方法。

    克隆原理
    通常,克隆对象应该独立于被克隆对象。为了达到这样的目的,可能需要在返回克隆对象前,修改克隆对象的字段,也就是说:

    1. 可变对象。需要将可变对象的引用替换为拷贝的引用。
    2. 不可变对象(初等类型或不可变引用)。克隆过程中就不需要修改super.clone的结果,一般来说虚拟机会创建新的对象。如下代码,super.clone返回的结构已经将ab完成了。
    public class Main implements Cloneable{
        private int a;
        private String b;
        @Override
        public Main clone() throws CloneNotSupportedException {
           return (Main) super.clone();
        }
    }
    

    Object类的clone方法
    Object类的clone方法执行的特定操作。

    1. 如果对象的类没有实现接口Cloneable,那么会抛出CloneNotSupportedException
    2. 所有数组被认为是默认实现了接口Cloneable,数组类型T[]clone方法的返回类型是T[],其中T是任何引用或初等类型。否则,此方法将创建此对象类的新实例,并使用此对象相应字段的内容初始化其所有字段;字段的内容本身不会被克隆。由此可见,此方法执行此对象的“浅拷贝”,而不是“深拷贝”操作。

    Object类没有实现Cloneable接口,所以调用clone方法会抛CloneNotSupportedException

    4 notify

    唤醒等待获取对象监控器(monitor)的一个线程。如果有多个线程在等待,则被唤醒线程是不确定的。

    被唤醒线程不能立即执行,而是等到当前线程释放对象锁才可以执行。被唤醒的线程需要与任何其他线程竞争,这其中不乏主动基于此对象同步的线程。

    该方法只能由对象monitor拥有者线程来调用。线程成为monitor拥有者方式有:

    1. synchronized实例方法。
    2. synchronized语句块。
    3. synchronized静态方法。即Class实例的方法。

    Java对象的实现由Monitor Object、Monitor Lock和Monitor Condition三部分组成。[2]

    5 wait

    使当前线程等待,直到另一个线程调用notify方法或notifyAll方法、或者超时。

    当前线程必须用于对象monitor。

    此方法使当前线程\text{T}被放入这个对象的等待集中,然后释放所有这个对象上的同步声明。线程\text{T}进入休眠状态,直到:

    1. 其他线程调用对象的notify,线程\text{T}恰好被选中。
    2. 其他线程调用对象的notifyAll
    3. 其他线程调用\text{T}interrupt方法。
    4. 用尽超时时间。

    线程唤醒后,会先从等待集合中移除,并重新进入调度行列。被唤醒线程与其他线程同步以常规方式竞争对象同步的权限。一旦获取了对象所有权,所有的对象同步声明将恢复为原状(quo ante),即调用wait时的状态。

    线程也可以在不被通知、中断或超时的情况下被唤醒,即所谓的“虚假唤醒”。虽然,这种情况在实践中很少发生,但应用程序必须通过测试本应导致线程被唤醒的条件,并在条件不满足时继续等待来防范这种情况。换句话说,等待应该总是以循环的形式出现,就像这样:

    synchronized (obj) {
        while (<condition does not hold>)
            obj.wait(timeout);
        // Perform action appropriate to condition
    }
    

    如果当前线程在等待之前或等待期间被任何线程中断,则抛出InterruptedException。只是在对象的锁状态恢复之前,不会抛出。也就是说,如果当前线程被中断时,对象monitor被其他线程拥有,当前线程只有获得对象monitor才能够抛出异常

    注意,wait方法在将当前线程放入此对象的等待集中时,只解锁此对象;在线程等待期间,当前线程可能同步的任何其他对象都将保持锁定状态。

    6 finalize

    当垃圾回收器确定对象不再被引用时,垃圾回收器调用对象的这个方法。子类重写finalize方法,用于释放系统资源或执行其他清理工作。

    关于finalize一般约定:

    1. 当不再有任何存活线程以任何方式访问该对象时,则调用finalize,除非已经被某个对象或类执行finalize时调用过。

    finalize方法的用途:

    1. 使此对象对其他线程再次可用。
    2. 在对象被回收之前执行清理操作。例如,I/O连接对象的finalize方法可能会执行显式I/O事务,以便在对象被回收之前断开连接。

    Java并不保证哪个线程将调用对象的finalize方法,但是,可以保证的是调用finalize的线程在调用finalize时不会持有任何用户可见的同步锁。如果finalize方法执行时抛出未捕获的异常,则将忽略该异常,并终止执行该对象的finalization。

    调用对象finalize方法之后,虚拟机不会做任何动作,直到它再次确定不再有任何活跃线程以任何方法引用该对象,包括其他即将终止的对象或类可能执行的操作,这时,对象可能会被丢弃。

    对于一个对象,finalize方法不会被虚拟机调用多次,也就是说最多一次。

    代码实例:

    static class Test {
        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            System.out.println("Finalized!!!");
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                Test test = new Test();
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread().getName() + " finished");
        });
    
        thread.start();
        thread.join(); // 如果注释掉,则不会执行finalize
    
        System.gc();
    
        TimeUnit.SECONDS.sleep(10);
    }
    
    

    参考资料

    1. Object
    2. 关于synchronized的Monitor Object机制的研究

    相关文章

      网友评论

          本文标题:Object类简介

          本文链接:https://www.haomeiwen.com/subject/ainsxhtx.html