源码系列【1】:java.lang.Object

Object类

  • 万物父类,用源码解释来说就是is the root of the class hierarchy.

registerNatives()

  • 关于native,是Java的本地方法,通过JNI调用C系列的dll文件实现。
/**
     * 一个本地方法,具体是用C(C++)在DLL中实现的,然后通过JNI调用
     */
    private static native void registerNatives();

    /**
     * Object 初始化的时候自动调用registerNatives();
     */
    static {
        registerNatives();
    }

getClass()

 /**
     * 返回运行时类的class,输出的话就是:class java.lang.Object
     * @return
     */
    public final native Class<?> getClass();
  • Returns the runtime class of this {@code Object}.
  • 返回这个对象的类型,注意这里是对象,如果是int a=0;的a不是对象,不具有 getClass()方法
    在这里插入图片描述
  • 但是像String这种封装的类所产生的对象是有的。

hashCode()

  • 是个接口,返回一串Hash码:a hash code value for this object.
  • 解释中说是为需要hash code的类准备的方法,如HashMap等This method is supported for the benefit of hash tables such as those provided by {@link java.util.HashMap}.
public native int hashCode();

equals()

  • 这里有段很重要的话:这段话衍生的问题我在面试中遇见过~
  • Note that it is generally necessary to override the {@code hashCode}
    method whenever this method is overridden, so as to maintain the
    general contract for the {@code hashCode} method, which states
    that equal objects must have equal hash codes.```
  • necessary to override the {@code hashCode}使用equals()就必须同时override hashCode(),也就是两个对象equals的前提是他们拥有同一个hash code,这个涉及到hashCode的常规协定

hashCode 的常规协定是:

  • 1.在应用程序执行期间,如果一个对象用于equals()方法的属性没有被修改的话,
    那么要保证对该对象多次返回的hashcode值要相等。
  • 2.如果2个对象通过equals()方法判断的结果为true,那么要保证二者的hashcode值相等。
  • 3.如果2个对象通过equals()方法判断的结果为false,那么对二者hashcode值是否相等并没有明确要求。
    如果不相等,那么能够提升散列表的性能。
  • 这里比较的是对象的内存地址,跟String.equals方法不同,它比较的只是对象的值
    public boolean equals(Object obj) {
        return (this == obj);
    }

clone()

  • 如果类没有实现clone方法,则会抛出CloneNotSupportedException错误,所有数组(arrays)都实现了cloneable接口
       /**
     * 如果类没有实现clone方法,则会抛出CloneNotSupportedException错误,所有数组(arrays)都实现了cloneable接口
     * @return
     * @throws CloneNotSupportedException
     */
    protected native Object clone() throws CloneNotSupportedException;

Clone 有关的几个问题(速度与深浅复制)
  • 问题1:对象的创建有多中方式,类似 new 、getInstance、clone等 clone有什么好处?
    • 参考大佬的测试代码,调用底层dll,快:
public class ObjectCloneTest1 {
    static final int N = 100000;
    public static void main(String[] args) {
        final Date date = new Date();
        {
            final long startTime = System.currentTimeMillis();
            for (int i = 0; i < N; i++) {
                Date date2 = (Date) date.clone();
            }
            final long endTime = System.currentTimeMillis();
            System.out.println("clone:" + (endTime - startTime) + "ms");
        }
        {
            final long startTime = System.currentTimeMillis();
            for (int i = 0; i < N; i++) {
                final Calendar cal = Calendar.getInstance();
                cal.setTime(date);
                final Date date2 = cal.getTime();
            }

            final long endTime = System.currentTimeMillis();
            System.out.println("Calender.setTime:" + (endTime - startTime) + "ms");
        }
    }
}

输出是:
clone:8ms
Calender.setTime:153ms

  • 问题2:对象调用clone方法生成的对象 和 原对象是否还有什么关联关系?
    • Object是属于浅复制,新(拷贝产生)、旧(元对象)对象不同,但是内部如果有引用类型的变量,新、旧对象引用的都是同一引用。
  • 问题3 : 对象clone存在 “浅复制”、“深复制”概念,怎么区分?
    • 需要区别2个对象是否存在相同的引用或对应的内存地址是否存在共用情况,若存在则 该次clone为 “浅复制”,否则为“深复制”, 而且Object的clone方法是属于 “浅复制”
    • 就比如:Person A 和Person B , A==B是false(地址不同) 但是A.getName()==B.getName()(地址同)是true,这是浅复制,深复制的话,就连name也复制了。

toString

  • toString没有重写的话就是如下,类名@hashCode
  • 但是我们一般会重写toString,这是个很重要的方法
    public String toString() {
        return getClass( ).getName( ) + "@" + Integer.toHexString(hashCode( ));
    }

notify、notifyAll与wait

  • 多线程相关内容,注释是我目前的理解
  • 顺便提一句,final关键词表示不能被重写
	/**
     * 1、唤醒一个在次对象监视器wait的线程
     * 2、线程被唤醒且被执行的条件是,当前线程释放了运行时上的锁
     * 3、被唤醒的线程会与需要相同资源的线程进行竞争
     */
    public final native void notify();
    /**
     * 同notify,只不过是唤醒此对象监视器上的所有线程
     */
    public final native void notifyAll();
    /**
     * 1、使得当前运行的线程进入等待状态(进入等待池)
     * 2、当前线程必须拥有此对象的监视器
     * 3、当线程被唤醒、或者timeout=0(等待时间到了),会重新进入运行池
     * 4、如果被interrupted,即中断了,则抛出InterruptedException,如果是等待状态被中断,则等到恢复运行的时候抛出。
     * @param timeout
     * @throws InterruptedException
     */
    public final native void wait(long timeout) throws InterruptedException;
    /**
     * 1、使得当前线程等待,直到其他线程调用notify(或notifyALl),或等待时间已到
     * 2、实现上很简单,nanos>0即可,在jdk1.7及一下nanos内部似乎是变过的,具体代码如下
     *      if(nanos >= 500000 || (nanos != 0 && timeout == 0)){timeout++;}
     *      是半毫秒以上的nanos才会使得timeout++
     * 3、其他机制类似于wait(long timeout)毕竟调用的它
     * @param timeout
     * @param nanos
     * @throws InterruptedException
     */
    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);
    }
    /**
     * 调用wait(0)
     * @throws InterruptedException
     */
    public final void wait() throws InterruptedException {
        wait(0);
    }
    

finalize()

  • 垃圾回收机制相关
 /**
     * 垃圾回收机制相关,当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
     * @throws Throwable
     */
    protected void finalize() throws Throwable {
    }
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读