Java基础类源码分析:Object 全球百事通
1 大纲
java.lang.Object是所有类的父类,默认继承,而且java.lang包下的所有类都由编译器自动导入,不需要显示import,因为用的多,提前加载可以提高运行时速度。
2 equals方法
"=="与equals的区别要看equals是如何重写的,在Object中两者意义等同,都是判断引用地址是否相同。在String中equals比较的是内容。
(资料图片仅供参考)
在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比较。
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 { }}