Object

作者: sollian | 来源:发表于2018-05-29 17:53 被阅读4次

    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 (<condition does not hold>)
            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

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