Object

Object是所有对象的父类,包括数组。

public final Class getClass()

该方法返回对象在运行时的类型。

这里可以同.class方法做个对比。通常情况下,这两个方法是等价的,不同之处在于:

  1. getClass是实例方法,.class是类方法。
  2. getClass是运行时确定的,而.class在编译时就确定了。

比如:

public class JavaDemo {
    static class Parent {
    }

    static class Child extends Parent {
    }

    public static void main(String[] args) {
        Parent parent = new Parent();
        Child child = new Child();
        System.out.println(parent.getClass() + " " + Parent.class);
        System.out.println(child.getClass() + " " + Child.class);

        Parent proxy = parent;
        System.out.println(proxy.getClass());
        proxy = child;
        System.out.println(proxy.getClass());
    }
}

输出如下:

Parent Parent
Child Child
Parent
Child

public int hashCode()

返回对象的哈希值。该方法用来辅助涉及到哈希表的类,比如HashMap。
哈希值的通用约定如下:

  1. 在Java应用的一次执行过程中,一个对象如果equals方法涉及到的信息没有被修改,那么多次调用hashCode返回值应该相同。多次执行同一应用不做要求。
  2. 如果两个对象通过equals方法比较的结果是相等的,那么hashCode返回值相同。
  3. 如果两个对象通过equals方法比较的结果是不相等的,那么不要求hashCode返回值一定不相同。不过hashCode返回值不同有利于提高哈希表的性能。

该方法默认将对象的内存地址转化为整数值返回。

public boolean equals(Object obj)

判断两个非null对象是否相等。该方法遵循如下规则:
对于任意非null对象x、y、z,有:

  1. 自反性:即x.equals(x) == true
  2. 对称性:当且仅当y.equals(x) == true时,x.equals(y) == true
  3. 传递性:若x.equals(y) == true && y.equals(z) == true,则x.equals(z) == true
  4. 一致性:若equals方法中的信息没有被修改,则多次调用x.equals(y)返回值不变。
  5. x.equals(null) == false

"equals"方法和"=="的区别在于"=="比较的是左右两边是否是同一个对象,而"equals"可自定义,其默认实现同"=="。

需要注意的是,若重写了equals方法,则也需要同时重写hashCode方法,否则可能会违背hashCode方法的第二条约定。

clone

    protected Object clone() throws CloneNotSupportedException {
        if (!(this instanceof Cloneable)) {
            throw new CloneNotSupportedException("Class " + getClass().getName() +
                                                 " doesn't implement Cloneable");
        }

        return internalClone();
    }

拷贝当前对象并返回。这里的拷贝依赖于对象的类型。通常情况下,对任意对象x,有:

  1. x.clone() != x
  2. x.clone().getClass() == x.getClass()
  3. x.clone().equals(x)

但以上规则不是必须的。
通常来讲,返回的对象是通过调用super.clone()获得的,并且新对象与原对象相对独立。也就是说,若类只有原始类型或者不可变类型(比如String)的成员,直接返回super.clone()即可;若包含其他类型的对象,则需要进行“深拷贝”。

由clone方法的实现可知,要想调用clone,需要类实现Cloneable接口。数组类型实现了Cloneable接口,如果是可变对象的数组,默认实现的是浅拷贝。如下:

public class JavaDemo {
    private static class Car {
    }

    public static void main(String[] args) {
        Car car = new Car();
        Car[] cars = {car};
        Car[] cars2 = cars.clone();
        System.out.println(cars ==+ cars2);
        System.out.println(cars[0] == cars2[0]);
    }
}

结果为false true

protected void finalize() throws Throwable

在gc回收对象时调用。子类可覆写该方法来做一些清理工作。JVM无法确保该方法在哪个线程调用。如果该方法抛出未被捕获的异常,则该异常将被忽略,并且终止对该对象的清理。
该方法至多被调用一次。一般用来回收通过特殊渠道申请的内存,比如JNI和c代码。

wait(long millis)

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

使当前线程进入等待状态。
要调用该方法,当前线程首先要获取该对象的锁。调用后,当前线程会首先进入该对象的等待池,然后释放该对象的锁。当前线程进入休眠状态,直到以下任意条件触发:

  1. 其他线程调用了该对象的notify方法,并且恰好该线程被唤醒。
  2. 其他线程调用了该对象的notifyAll方法。
  3. 其他线程调用了该线程的interrupt方法。
  4. 该线程的等待时间超过了millis毫秒。

触发以上任意条件后,该线程会被移出该对象的等待池,进入该对象的锁池,与其他线程竞争,等待获取该对象的锁。获取到锁之后,线程会恢复到调用wait之前的状态。

除上述条件外,线程也可能被意外唤醒。虽然这个可能性很小,但是应用应该保证线程在正确条件下被唤醒,如果条件不对,应继续等待。该方法的调用形式如下:

synchronized (obj) {
    while ()
        obj.wait(timeout);
    ... // Perform action appropriate to condition
}

需要注意的是,调用该对象的wait方法后,该线程之后释放该对象的锁,其他对象的锁不会释放

public final native void wait(long millis, int nanos) throws InterruptedException

同wait(long millis)。
等待的最大时间为1000000 * millis + nanos纳秒

public final native void wait() throws InterruptedException

与wait(0)相同。

public final native void notify()

唤醒任意一个处于该对象等待池中的线程。

public final native void notifyAll()

唤醒所有处于该对象等待池中的线程。

notify和notifyAll也需要在synchronized语法块中调用。

你可能感兴趣的:(Object)