Object类

Object类源码阅读:

  Object类中包含的方法:

  1.private static native void registerNatives();

static {

    registerNatives();
}
说明:就是对几个本地方法进行注册

2.public final native Class<?> getClass();
说明:返回object运行时类。返回的是类对象。

3.public native int hashCode()
获取对象的哈希值。不可以根据hashcode值判断两个对象是否相等。因为不同的对象可能会生成相同的hashcode值。虽然不能根据hashcode值判断两个对象是否相等,
但是可以直接根据hashcode值判断两个对象不等,如果两个对象的hashcode值不等,则必定是两个不同的对象。如果要判断两个对象是否真正相等,必须通过equals方法。
如果要判断两个对象是否真正相等,必须通过equals方法。

  也就是说对于两个对象,如果调用equals方法得到的结果为true,则两个对象的hashcode值必定相等;

  如果equals方法得到的结果为false,则两个对象的hashcode值不一定不同;

  如果两个对象的hashcode值不等,则equals方法得到的结果必定为false

  如果两个对象的hashcode值相等,则equals方法得到的结果未知。

重写equal方法,必须要重写hashCode方法。因为通过equal判断相等的两个对象,hashCode方法必须返回相同的hashCode值。

4. public boolean equals(Object obj) {

    return (this == obj);
}

对于非空对象的引用,x.equals(x)应该返回true

对于非空对象的引用,x.equals(y) 返回truey.equals(x)也应该返回true

传递性,x.equals(y) 返回truey.equals(z)返回true, 则x.equals(z)也应该返回true

对于非空对象,x.equals(null)应当返回false

只有当xy是同一对象时, x==y才会返回true

所以,当重写equals方法时,有必要重写hashCode方法,因为equals方法返回true的两个对象,其hash值必须相等。

5.protected native Object clone() throws CloneNotSupportedException;

一般来说,x.clone() != x返回truex.clone().getClass() == x.getClass()返回true,但是并非必须。

x.clone().equals(x)并非绝对的必要条件。

惯例,该方法返回的对象可以通过调用super.clone获得。如果一个类和他的父类遵守这个惯例,则x.clone().getClass() == x.getClass()

按照惯例,通过该方法返回的对象和原对象应该是独立的。为了达到这个独立性,有必要在返回该对象前,修改一个或多个字段。这意味着,被复制对象的深层次结构也应该被复制,并替换引用。如果一个对象只包含基本数据类型,则其字段不需要被修改。

如果一个类要实现clone方法。需要实现Cloneable接口,否则就会抛出CloneNotSupportedException。所有的数组都被认为实现了该接口。该接口只复制了字段,字段中的内容没有进行复制,所以该方法是浅复制,而不是深复制。

Object对象本身没有实现Cloneable接口,所以调用Object里面的clone方法会抛出CloneNotSupportedException异常。

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

返回对象的字符串表示形式。返回的结果要简洁扼要,便于阅读。推荐所有的子类重写该方法。Object对象的toString方法返回getClass().getName() + '@' + Integer.toHexString(hashCode()).

  1. public final native void notify();

唤醒一个等待该对象监视器的线程。如果有多个线程在等待获取锁,其中一个线程将被唤醒。
被唤醒线程的选择是随机的。被唤醒的线程无法继续执行,直到当前线程释放对象的锁。被唤醒线程将会和其他使用synchronize方法获取锁的线程进行竞争。被唤醒的锁享受并不可靠的优先级。
一个线程成为线程监听器拥有者的方式有三种:
1.对象的synchronized方法
2.对象的synchronized代码段
3.类对象的静态synchronized方法,获取类队形本身的锁

  1. public final native void notifyAll();

唤醒所有等待该对象监听器的线程。被唤醒线程不能继续运行,直到当前线程释放对象的锁。被唤醒线程将和其他线程同等竞争获取对象的锁。被唤醒线程并不具有可靠的优先权去获取对象的锁。该方法只能被拥有对象监听器的线程使用。如果当前线程并未拥有该对象的监听器,调用该方法将会抛出IllegalMonitorStateException异常。

  1. public final native void wait(long timeout) throws InterruptedException;

该方法导致当前线程等待,知道其他线程调用notify()或者notifyAll(), 或者经过特定的时间。当前线程必须拥有对象监视器。

该方法会让当前线程把自己放到改对象对应等待队列中,然后放弃所有对该对象同步请求,
线程将不会参与调度,并保持休眠状态,直到下面四种情况之一发生:
1.其他线程调用该对象notify方法, 并且该线程被选中成为被唤醒的线程。
2.其他线程调用该对象notifyAll方法
3.其他线程interrupt该线程
4.经过特定时间,如果timeout0,则需要等待,知道被通知。

该线程被移出等待的集合,并且变成可以调度的线程。
该线程将会与其他线程针对该对象的synchronize进行一般情况下的竞争。一旦该线程获得锁,该线程对该对象的同步申请都会恢复原状,即回到wait方法被调用时的状态。然后,线程将从wait方法中返回。在从wait方法返回过程中,该对象和线程的同步状态和wait方法被调用时的一致。

除了唤醒,中断,超时以外,一个线程也可以被唤醒,这称为虚假唤醒。实际中很少发生这种情况。应用必须避免这种情况,可以通过测试该线程等待的条件,如果条件不满足,则继续等待。也就是说,等待应该放到循环中,就像下面这样:

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

如果该线程在等待中之前和等待中被其他线程中断,InterruptedException将会被抛出。在该对象的锁的状态被重置前,异常不会被抛出。

注意,该对象的对应的等待队列中的线程,只能有该对象进行解锁。该线程等待过程中,如果该线程拥有的其他对象的同步,其他对象将保持锁定。该方法只能被该对象的监视器拥有者使用。

  1. 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);
    }

该方法导致当前线程等待,直到另外一个线程调用notify()或者notifyAll()方法唤醒。或者其他线程中断该线程,或者经过了固定的时间。该方法和单参数方法类似。但是该方法允许精确控制放弃前等待通知的时间。实际等待的时间是以纳秒为单位的,按照下面的公式计算:

1000000*timeout+nanos

在其他所有的方面,该方法做的事情和单参数方法是一致的。特别的,wait(0,0)wait(0)是一致的。

当前线程必须拥有该对象的监视器。线程释放监视器的拥有权和等待,知道下面两者之一发生:

  1. 另外一个线程通过notify或者notifyAll唤醒等待该对象监视器的线程。
  2. 超时时间,经过timeout秒和nanoseconds毫秒之和。

线程继续等待,直到该线程能重新获得监视器的拥有权,然后继续执行。和单参数方法类似,中断和虚假唤醒是有可能的,所以该方法应该用在循环中:

synchronized (obj) {

     while (<condition does not hold>)

         obj.wait(timeout, nanos);

         ... // Perform action appropriate to condition

}

该方法只能被拥有该对象监视器的拥有者调用。可以参见notify方法得知线程获得一个监视器拥有权的方法。

11.  public final void wait() throws InterruptedException {

   wait(0);

}

该方法导致当前线程等待,直到其他线程调用该对象的notify()或者notifyAll方法。换句话说,该方法的执行效果和wait(0)是一致的。当前线程必须拥有对象的监视器。线程释放监视器的拥有权和等待直到其他线程,使用notify或者notifyAll方法唤醒等待该对象的监视器的线程。和单参数方法一致,中断和虚假唤醒是有可能的。因此,该方法应该总是被用在循环中:

synchronized (obj) {

    while (<condition does not hold>)

        obj.wait();

        ... // Perform action appropriate to condition

 }

该方法只能被该对象监视器的拥有者调用。可以参见notify方法得知线程获得一个监视器拥有权的方法。

12.  protected void finalize() throws Throwable { }

当垃圾回收确定该对象没有多余的引用时,垃圾回收器会调用该方法。{@code finalize}的一般约定是,当Java™时调用它;当其他线程没有办法进入该对象时,虚拟机会决定调用该方法。该方法调用一些方法,包括使对象对其他线程重新可见。该方法的一般目的是在对象不能撤销的丢弃前执行一些清理工作。例如,在对象呗持久化丢弃钱,该方法会断开该对象的一些连接,这些连接用于输入和输出。

对象的finalize方法没有做什么特殊的操作,仅仅是正常返回。子类可能会重写该方法。对于给定的对象,java编程语言不能保证哪个线程会调用这个方法。但是调用该方法的线程必须拥有用户可见的同步锁。如果,该方法被捕获到异常,异常将会被忽略,析构也将终止。

当一个对象的该方法被调用后,将不会有进一步的动作被执行,直到虚拟机发现其他线程没有任何方法进入该对象,这些方法包括将要被丢弃的其他对象或类对该对象采取了操作。

该方法被虚拟机调用的次数不会超过一次。该方法抛出的任何异常都会导致对象析构的终止,但是这些异常会被忽略。

原文地址:https://www.cnblogs.com/chwy/p/10652416.html