美文网首页
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类简介

    1 hashCode hashCode的一般约定为: 同一个程序中多次调用返回相同的值。不会为equals方法比较...

  • 深入了解Object对象

    1、类 Object简介 类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包...

  • java -Object :equals()、tostring(

    1 Object类的简介 1)在Java类继承结构中,java.lang.Object类位于顶端; 2)如果定义一...

  • java.lang.Object

    一、简介 Object类是除自己外所有java类的终极父类。当然,数组也继承了Object类。然而,接口是不继承O...

  • Java并发编程,Condition的await和signal等

    Condition简介 Object类是Java中所有类的父类, 在线程间实现通信的往往会应用到Object的几个...

  • wait()、sleep()方法介绍

    简介 1、wait()、notify()、notifyAll() 属于Object类中的方法; 2、wait()、...

  • Object类及常用方法简介

    Object类是一个特殊的类,是所有类的父类,是java中唯一没有父类的类,如果一个类没有用extends明确指出...

  • Object类及其常用方法简介

    Object类是一个特殊的类,是所有类的父类,如果一个类没有用extends明确指出继承于某个类,那么它默认继承O...

  • Class 的继承

    简介 Object.getPrototypeOf() super 关键字 类的 prototype 属性和prot...

  • Android 进阶之 AsyncTask

    简介 AsyncTask 直接继承于 Object 类,位置为 android.os.AsyncTask。首先明确...

网友评论

      本文标题:Object类简介

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