Java源码赏析(一)Object 类


写这个系列的原因,其实网上已经有无数源码分析的文章了,多一篇不多,少一篇不少,但为什么还要写这部分文章呢?
于私,
其一,上班族已经很久没有打过完整的一整段有意义的话,算是锻炼个人的书写、总结能力,
其二,别人的代码永远是别人的,只有亲自做过才知道其中的滋味,
其三,若干年后如果博客园还在,也算是一段美好的回忆。
于公,网上有大部分的文章属于copy,虽然copy没问题,但是看多了会觉得千篇一律,而且少了很多技术细节,我打算写得详细一点,啰嗦一点,如果能让刚刚入门Java的同学有所收获,那就心满意足了。

首先贴上 Object.java 的代码。
package java.lang;

public class Object {

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

    /** 通过对象获得一个类的实例对象,通过Class<?>,可以获取这个类的构造方法、方法和属性等。*/
    public final native Class<?> getClass();

    /** 返回对象的hash code。主要用于switch 字符串, hashMap等散列集。*/
    public native int hashCode();

    /** 
     * 对比对象是否相等。最好和hashCode一起重写。
     * 1.equals()对比对象值是否相同
     * 2.== 对比两个对象引用是否一致,是否为同一个对象
     */
    public boolean equals(Object obj) {
        return (this == obj);
    }

    /** 复制一个对象。类要使用该方法,需要实现Cloneable接口。*/
    protected native Object clone() throws CloneNotSupportedException;

    /** 转化为String时自动调用的方法,主要用于打印到控制台或日志文件,默认为类名@加十六进制的哈希值(基本不可读),最好重写。*/
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

    /** 同步相关代码等之后的Java随谈中详细介绍*/
    public final native void notify();

    public final native void notifyAll();

    public final native void wait(long timeout) 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);
    }

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

    /** 向垃圾回收器“报告”回收该对象,可以通过重写这个方法实现来检测垃圾回收的时机。*/
    protected void finalize() throws Throwable { }
}  

 

这里面每一个方法都十分重要,但有几个方法在很多时候都需要重写。我们先着重讲解下面这几个:

一、equals()和hashCode()

不重写equals比较的是对象是否为同一对象。不重写hashCode()会影响Map、Set的操作。

如何重写?

  1. 在之前的Java版本需要手动重写这两个方法。
  2. 如果你使用的是Java7以上的版本,可以使用Objects.deepEquals(Object a, Object b)和Objects.hash(Object... values),方便地进行方法重写。
  3. 如果你依赖了Lombok,可以使用@EqualsAndHashCode。

  

二、toString()

在Java中,当要连接对象和字符串时,会自动调用对象的toString()方法,默认为 类名@16进制哈希值,最好重写,增加可读性。

Object a = new Object();
String s = a + " ,hello";

同样,如果你依赖了Lombok,可以使用@ToString。

 

 

相关阅读

1. ORACLE JAVA 教程 Object

posted @ 2020-08-31 19:01  Kwanwooo  阅读(223)  评论(0编辑  收藏  举报