Java中的Object类

Java程序是由类所组成的。而Object类是所有类的基类,Object中的方法也应当直接存在于派生类中或者由派生类所重写。但是无论如何,都应当了解基类中的方法能够做什么事情,怎么做,因为Object中的方法五一是java学习中最为基础的知识。

registerNatives?

一上来我就被class Object代码块中的这样两行代码整蒙了:

    private static native void registerNatives();
    static {
        registerNatives();
    }

首先定义了一个registerNatives方法,与通常的java方法不同,我并没能用Go to Declaration找到这个方法的源码,然后由看了一下前面的关键字,native?这是个啥?

搜了一下,发现native修饰的方法是定义在本地代码中的,另有其他语言来实现,主要是用来实现对操作系统底层的访问和操作。具体实现上,是包括在JDK的Java Native Interface(JNI)包当中的。可以把java语言和其他语言嵌套在一起。

所以这个registerNatives做的是与本地的交互工作,引用StackOverflow上的说法,这个方法具体完成的工作就是在java中给本地方法一个映射,使得java在运行时可以直接调用本地方法,而这个类方法时static的,也就是在Object类加载时最先执行的,Object方法又必然在所有类之前加载。因此,这个方法一定会在其他方法之前运行,保证其他方法在运行时可以准确的找到本地方法。

构造方法

    @HotSpotIntrinsicCandidate
    public Object() {}

就是建立一个简单的Object对象,初始化函数本身很平实,陌生的敌方就是 @HotSpotIntrinsicCandidate这个注释,表示的是JVM中对这一方法有一套单独的实现方法。

其他本地方法

@HotSpotIntrinsicCandidate
public final native Class<?> getClass();

@HotSpotIntrinsicCandidate
public native int hashCode();

getClass主要是用于反射,通过给定具体的对象,获取其所从属的类对应的Class类。
hashCode是返回对象的哈希值,用于今后要说的HashTable和HashSet等。

    @HotSpotIntrinsicCandidate
    protected native Object clone() throws CloneNotSupportedException;

又是一个native方法,还有一点需要注意,就是java中的clone是进行深复制,即复制所有的引用子对象。

equals

public boolean equals(Object obj) {
        return (this == obj);
    }

在各种笔试面试题中经常出现的万恶之源。这里看一下,原方法是必须得是引用相同的对象才可以!这点切记。但是为啥到了String字符串比较就不一样了呐?来看一下String类中的代码:

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String aString = (String)anObject;
            if (coder() == aString.coder()) {
                return isLatin1() ? StringLatin1.equals(value, aString.value)
                                  : StringUTF16.equals(value, aString.value);
            }
        }
        return false;
    }

是因为String类重写了equals方法,在地址不相等时,通过比较字符串的值来补救。

toString

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

toString方法就是将一个Object对象用String的方法打出来,返回类名称+@+这个对象的哈希码。

线程相关

wait与notify、notifyall是java中常用的两个线程间通信方法,具体的使用可以详见如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例。这里主要说一下参数的作用。
先来看一下wait函数及其重载。

public final native void wait(long timeoutMillis) throws InterruptedException;

public final void wait() throws InterruptedException {
  wait(0L);
}

 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);

先来看一下第一个wait,只有一个long参数,就是让当前的线程放弃此对象的锁并且监视该对象是否有notify或者notifyall的动作,并且最多等待一个timeoutMillis的时长,这段时间内如果有其他线程进行了notify与notifyall,那么就继续,如果超时,继续运行。第二个是无参的wait就是参数为0的情况,无论过多久,该进程都要去等待该对象被唤醒;第三个就是添加了一个毫秒,将毫秒转化为微秒级别。
接下来看一下notify和notifyall

    @HotSpotIntrinsicCandidate
    public final native void notify();

    @HotSpotIntrinsicCandidate
    public final native void notifyAll();

这两个也是一对孪生兄弟,两者的作用也相差无几。notify是一个小气鬼,每次只会通知一个在wait该对象的线程,但是究竟选择哪个线程呐?答案是随机,因此notify本身会造成一些不确定性。二notifyAll则好多了,一次性的唤醒所有在等待该对象的线程。

finalize

    @Deprecated(since="9")
    protected void finalize() throws Throwable { }

在该对象被回收时所执行的方法,与C++中的析构函数不同,这一语句只会被执行一次,之后即便是该对象没有真正的被GC所回收,也不会再次运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值