Java基础类源码分析:Object

1 大纲

java.lang.Object是所有类的父类,默认继承,而且java.lang包下的所有类都由编译器自动导入,不需要显示import,因为用的多,提前加载可以提高运行时速度。

image.png

2 equals方法

"=="与equals的区别要看equals是如何重写的,在Object中两者意义等同,都是判断引用地址是否相同。在String中equals比较的是内容。


(相关资料图)

//Objectpublic boolean equals(Object obj) {    return (this == obj);}//Stringpublic boolean equals(Object anObject) {    if (this == anObject) {        return true;    }    return (anObject instanceof String aString)            && (!COMPACT_STRINGS || this.coder == aString.coder)            && StringLatin1.equals(value, aString.value);}public static boolean equals(byte[] value, byte[] other) {    if (value.length == other.length) {        for (int i = 0; i < value.length; i++) {            if (value[i] != other[i]) {                return false;            }        }        return true;    }    return false;}

equals方法含义按需要重写,但需要满足Java规范:

在Java规范中,对equals方法的使用必须遵循以下几个原则:1)自反性。对于任何非空引用值x,x. equals(x)都应返回true。2)对称性。对于任何非空引用值x和y,当且仅当y. equals(x)返回true时,x.equals(y)才应返回true。3)传递性。对于任何非空引用值x、y和z,如果x. equals(y)返回true,并且y.equals(z)返回true,那么x. equals(z)应返回true。4)一致性。对于任何非空引用值x和y,多次调用x. equals(y)始终返回true或始终返回false,前提是对象上equals比较中所用的信息没有被修改。对于任何非空引用值x,x. equals(null)都应返回false。对于任何非空引用值x,x. equals(null)都应返回false。

3 hashCode方法

hashCode是一个本地方法,用来加快equals比较,但两个不同对象的哈希值难免有冲突,hashCode和equals的关系如下:

如果equals返回true,则hashCode一定相等;如果equals返回false,则hashCode可能相等。也就是说如果hashCode不相等,那么equals一定不相等。注:Object中的hashCode方法返回的是对象的内存地址,有特殊要求可重写。

@IntrinsicCandidatepublic native int hashCode();

hashCode主要用于Map、Set等容器中,当向容器添加元素时需要去一个个比较是否有相等的元素,直接调用equals效率太慢。可以先比较hashCode,如果hashCode不一样则equals必然返回false,如果hashCode一样再调用equals比较。

image.png

4 wait

wait方法也是Object类本地方法,一般用于synchronize代码块中,作用是释放锁并阻塞线程,唤醒方法是notify/notifyAll。

sleep方法是Thread类方法,调用了sleep0本地方法,作用是不释放锁但阻塞线程。

await方法是ConditionObject/ReentrantLock类的方法,作用是释放锁并阻塞线程,唤醒方法是signal/signalAll。

public final void wait() throws InterruptedException {    wait(0L);}public final void wait(long timeoutMillis) throws InterruptedException {    long comp = Blocker.begin();    try {        wait0(timeoutMillis);    } catch (InterruptedException e) {        Thread thread = Thread.currentThread();        if (thread.isVirtual())            thread.getAndClearInterrupt();        throw e;    } finally {        Blocker.end(comp);    }}// final modifier so method not in vtableprivate final native void wait0(long timeoutMillis) throws InterruptedException;public final void wait(long timeoutMillis, int nanos) throws InterruptedException {    if (timeoutMillis < 0) {        throw new IllegalArgumentException("timeoutMillis value is negative");    }    if (nanos < 0 || nanos > 999999) {        throw new IllegalArgumentException(                            "nanosecond timeout value out of range");    }    if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {        timeoutMillis++;    }    wait(timeoutMillis);}
public static void sleep(long millis) throws InterruptedException {    if (millis < 0) {        throw new IllegalArgumentException("timeout value is negative");    }    if (currentThread() instanceof VirtualThread vthread) {        long nanos = MILLISECONDS.toNanos(millis);        vthread.sleepNanos(nanos);        return;    }    if (ThreadSleepEvent.isTurnedOn()) {        ThreadSleepEvent event = new ThreadSleepEvent();        try {            event.time = MILLISECONDS.toNanos(millis);            event.begin();            sleep0(millis);        } finally {            event.commit();        }    } else {        sleep0(millis);    }}private static native void sleep0(long millis) throws InterruptedException;

await具体细节请看Java多线程:条件变量

public final void await() throws InterruptedException {    if (Thread.interrupted())        throw new InterruptedException();    ConditionNode node = new ConditionNode();    int savedState = enableWait(node);//加入条件队列    LockSupport.setCurrentBlocker(this); // for back-compatibility,将AQS对象设置到thread中    boolean interrupted = false, cancelled = false, rejected = false;    while (!canReacquire(node)) {//如果被唤醒进入同步队列后就可以跳出循环        if (interrupted |= Thread.interrupted()) {            if (cancelled = (node.getAndUnsetStatus(COND) & COND) != 0)                break;              // else interrupted after signal        } else if ((node.status & COND) != 0) {            try {                if (rejected)                    node.block();                else                    ForkJoinPool.managedBlock(node);//阻塞线程,最终会调用LockSupport.park()            } catch (RejectedExecutionException ex) {                rejected = true;            } catch (InterruptedException ie) {                interrupted = true;            }        } else            Thread.onSpinWait();    // awoke while enqueuing    }//被唤醒    LockSupport.setCurrentBlocker(null);    node.clearStatus();////lock.lock()方法:acquire(null, arg, false, false, false, 0L);//重新获取锁时已原来的savedState    acquire(node, savedState, false, false, false, 0L);//重新获取锁,此时该节点已经进入了同步队列,有可能直接tryAcquire成功跳出循环,也可能需要两次循环修改node.status为WAITING、park。    if (interrupted) {        if (cancelled) {            unlinkCancelledWaiters(node);            throw new InterruptedException();        }        Thread.currentThread().interrupt();    }}

5 附录

public class Object {    @IntrinsicCandidate    public Object() {}    @IntrinsicCandidate    public final native Class getClass();//返回类对象用于反射    @IntrinsicCandidate    public native int hashCode();    public boolean equals(Object obj) {        return (this == obj);    }    @IntrinsicCandidate    protected native Object clone() throws CloneNotSupportedException;    public String toString() {        return getClass().getName() + "@" + Integer.toHexString(hashCode());    }    @IntrinsicCandidate    public final native void notify();    @IntrinsicCandidate    public final native void notifyAll();    public final void wait() throws InterruptedException {        wait(0L);    }    public final void wait(long timeoutMillis) throws InterruptedException {        long comp = Blocker.begin();        try {            wait0(timeoutMillis);        } catch (InterruptedException e) {            Thread thread = Thread.currentThread();            if (thread.isVirtual())                thread.getAndClearInterrupt();            throw e;        } finally {            Blocker.end(comp);        }    }    // final modifier so method not in vtable    private final native void wait0(long timeoutMillis) throws InterruptedException;    public final void wait(long timeoutMillis, int nanos) throws InterruptedException {        if (timeoutMillis < 0) {            throw new IllegalArgumentException("timeoutMillis value is negative");        }        if (nanos < 0 || nanos > 999999) {            throw new IllegalArgumentException(                                "nanosecond timeout value out of range");        }        if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {            timeoutMillis++;        }        wait(timeoutMillis);    }    @Deprecated(since="9", forRemoval=true)    protected void finalize() throws Throwable { }}
推荐DIY文章
100W快充!小米Type-C扩展坞仅149元 环球关注
元宇宙不止是畅想 “科幻畅想 元宇漫游” 主题论坛开讲 疫情之后京城首场元宇宙科技概念展亮相石景山
Win10命令提示符已被系统管理员停用如何解决 为什么会出现这种情况
如何用一键ghost安装win7 如果你还对装系统有疑问 可以看看本教程
【新要闻】win10所有word文档都打不开怎么办 建议重新选择word程序
怎么升级Win10创意者更新?感兴趣的用户可以一起来体验看看|快看
精彩新闻

超前放送