JAVA源码阅读-Object类

Object


Object类是所有类层级结构中的根,是所有类的超类,包括arrays在内都会实现Object类的方法。

(Object类中大部分方法都是由带有native标识符的外部方法(如c或c++)实现,想钻研的可看这篇文章JNI(java-native-interface)以及查看jni源码实现。)
源码来自jdk1.8.0_65版本


registerNatives()及静态方法*

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

对应c中

	//路径:D:\mydoc\openSource\openjdk\jdk\src\share\native\java\lang\Objcet.c
	Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
	{
	    (*env)->RegisterNatives(env, cls,
	                            methods, sizeof(methods)/sizeof(methods[0]));
	}
	//路径:C:\Java8\jdk1.8\include\jni.h
    jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,
                         jint nMethods) {
        return functions->RegisterNatives(this,clazz,methods,nMethods);
    }
    

getClass*

  • 返回该对象运行时的类——该对象静态同步方法锁定的类
  • 表达式:Class<? extends |X|>
  • 返回值该类实际运行时的对象
  • 例:
Number n = 0;
Class<? extends Number> c = n.getClass();
System.out.println(c);

此时输出为class java.lang.Integer
而将n改为0.0,输出的结果将是怎样呢?


hashCode***

  • 返回该对象的哈希值
  • 如果该对象的equals方法没有改变,它在java应用中(jvm?)不论被调用执行多少次,hash不变。(否则hash不必保持一致)
  • 如果两个对象equals相等,则hashcode相等。
  • 两个对象unequals,hashcode可以相等,但尽量使其不等以提高性能。
  • hashcode值是通过将对象内存地址转化的整数

equals***

equals方法用来指示其他对象是否等于该对象,在非空对象引用上实现如下等价关系

  • 对于任何x.equals(x)都返回true
  • 对于任何x,y,如果x.equals(y)为true,则y.equals(x)必然为true
  • 如果有x,y,z,如果x.equals(y) returns true并且y.equals(z) returns true,则必然有x.equals(z) returns true(怎么像数学公式)
  • 如果x,y没有改变,不论调用多少次x.equals(y),其值保持不变。
  • x.equals(null) return false
  • 由于hashcode方法主要依赖于此方法,所以此方法重写时需重写hashcode方法,因为两个对象equals相等,则hash值相等
public boolean equals(Object obj) {
        return (this == obj);
    }

clone***

clone实现原理应该是为对象创建一个新的实例,然后利用反射,将被克隆的对象的值一一赋给克隆的对象,注意,是直接赋值,这也就意味着,如果被克隆对象的属性全是原始类型,则直接复制过来,即深拷贝,但如果是引用对象,则是赋给引用了,是浅拷贝。如果想要一定程度的深拷贝,则需要重写clone方法并将每个需要深拷贝的引用对象也实现Cloneable接口。
想看例子可直接参考这篇java对象拷贝

  • x.clone() != x true
  • x.clone().getClass() == x.getClass() 通常为true,有为false的吗?
    注意一定要实现Cloneable,否则会抛CloneNotSupportedException异常。
    重写的clone方法也有可能抛CloneNotSupportedException异常。

toString*

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

如上述代码,默认返回此对象的名称和hash值。
toString 方法目的是简单清楚的让人知道这个对象有什么属性,所以一般都要根据需求去重写。


notify/notifyAll**

简单来说就是对于共享(对象)资源(即加了synchronized关键字的函数),有且只有一个线程同时在调用该资源,该资源会被当前线程加锁,其他线程无法调用,而notify/notifyAll可以使其他线程唤醒,等待该资源被释放后,才有机会去竞争谁来使用此资源。而wait方法会使该线程休眠,失去竞争资源锁的机会。
共享资源如下,obj则为竞争的对象。

           synchronized (obj) {
               while (<condition does not hold>)
                   obj.notify();
               ... // Perform action appropriate to condition
           }
  • notify唤醒单个线程,使其等待共享资源的控制权。如果有多个线程,则会随机唤醒其中一个。
  • notifyAll将所有共享该资源对象的线程全部唤醒,然后具体谁将获得该资源的控制权(加锁)则取决于他们的优先级。
    具体可参考这篇文章java中的notify和notifyAll有什么区别?,真的是写的非常详细。

wait**

首先,此方法与notify对应,是将当前持有共享对象锁的线程去掉锁,使该线程进入休眠状态,休眠状态时不会与其他线程竞争对象的持有权的。

  • 此方法只能作用于对对象正在持有锁的线程。
  • 如果无参数,即obj.wait();则此线程会一直进入休眠状态,如果有参数,即wait(long timeout),则会在等待timeout唤醒。
  • 此方法会导致当前线程(称为t)将自身放置在此对象的等待集中,然后放弃对此对象的所有同步声明。出于线程调度的目的,线程t将被禁用,并处于休眠状态,直到发生以下几种情况之一:
    • 其他线程调用notify/notifyAll且此线程赢得了对此对象的控制权。
    • 其他线程打断了( interrupts)该线程。
    • 在等待了指定时间后。
  • 为避免在不恰当的时机wait或是notify,所有的wait或notify都应放在while循环中,且要明确触发条件condition
           synchronized (obj) {
               while (<condition does not hold>)
                   obj.wait(timeout);
               ... // Perform action appropriate to condition
           }
  • 如果此线程在等待前或是过程中被其他线程打断,将会抛InterruptedException异常。

至于wait(long timeout, int nanos)方法,我实在不知道具体意义。这是jdk1.8的源码

public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0) {
            timeout++;
        }

        wait(timeout);
    }

完全看不出所谓的精确时长,以及1000000*timeout+nanos体现在哪,只看见了 timeout++也就是+1?希望有人能帮助我理解这里。


finalize**

缺少实践,还需要学习GC内容。 先参考这篇文章java finalize方法总结、GC执行finalize的过程

此外Object中有关于线程的很多知识需要恶补。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值