JDK源码学习-----java.lang.Object

概述

/**
 * Class {@code Object} is the root of the class hierarchy.
 * Every class has {@code Object} as a superclass. All objects,
 * including arrays, implement the methods of this class.
 *
 * @author  unascribed
 * @see     java.lang.Class
 * @since   JDK1.0
 */

Object类是处于所有class的root等级的一个类。java中其他任何的类都是他的子类。所有的类包括数组都要实现这个类中的方法

Object类的源码如下所示:

public class Object {

    private static native void registerNatives();
    static {
        registerNatives();
    }
	public final native Class<?> getClass();
	public native int hashCode();
	public boolean equals(Object obj) {
        return (this == obj);
    }

	protected native Object clone() throws CloneNotSupportedException;
  	public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

	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 { }

以上就是Object类的所有的方法成员了。下面一个一个的来进行学习。

private static native void registerNatives();

在学习这个方法之前首先先了解一下java中的native关键字
在java当中,native关键字是用于与C语言或者C++语言进行协同工作的。被native修饰的方法都是操作系统实现的。java中共只是调用这个方法而已。总而言之java是跨平台的语言,既然是跨了平台,所付出的代价就是牺牲一些对底层的控制,而java要实现对底层的控制,就需要一些其他语言的帮助,这个就是native的作用了。

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

对于这个函数而言,java将这个方法的执行放到了一个静态代码快当中,也就是说一开始这个方法是最先被执行的。
这个方法就是为了注册这个类中的除这个类之外的其他本地方法。为什么要注册呢?

首先java调用本地方法要分为两个步骤:(https://blog.csdn.net/Saintyyu/article/details/90452826)
第一,通过System.loadLibrary()将包含本地方法实现的动态文件加载进内存;第二,当Java程序需要调用本地方法时,虚拟机在加载的动态文件中定位并链接该本地方法,从而得以执行本地方法。registerNatives()方法的作用就是取代第二步,让程序主动将本地方法链接到调用方,当Java程序需要调用本地方法时就可以直接调用,而不需要虚拟机再去定位并链接。

    /**
     * Returns the runtime class of this {@code Object}. The returned
     * {@code Class} object is the object that is locked by {@code
     * static synchronized} methods of the represented class.
     *
     * <p><b>The actual result type is {@code Class<? extends |X|>}
     * where {@code |X|} is the erasure of the static type of the
     * expression on which {@code getClass} is called.</b> For
     * example, no cast is required in this code fragment:</p>
     *
     * <p>
     * {@code Number n = 0;                             }<br>
     * {@code Class<? extends Number> c = n.getClass(); }
     * </p>
     *
     * @return The {@code Class} object that represents the runtime
     *         class of this object.
     * @jls 15.8.2 Class Literals
     */
    public final native Class<?> getClass();
class Class{
	Filed[] f;//Filed代表字段,可以存String,int存成员变量
	Constructor c;//存构造方法
	Method m;//存方法	
}

getClass方法的返回值是一个class对象,通过返回的class对象可以获取这个类所有的成员方法,类型为Method。同时也可以获取所有的成员变量,类型为Filed,也可以获取到构造方法,类型为constructor。

/**
     * Returns a hash code value for the object. This method is
     * supported for the benefit of hash tables such as those provided by
     * {@link java.util.HashMap}.
     * <p>
     * The general contract of {@code hashCode} is:
     * <ul>
     * <li>Whenever it is invoked on the same object more than once during
     *     an execution of a Java application, the {@code hashCode} method
     *     must consistently return the same integer, provided no information
     *     used in {@code equals} comparisons on the object is modified.
     *     This integer need not remain consistent from one execution of an
     *     application to another execution of the same application.
     * <li>If two objects are equal according to the {@code equals(Object)}
     *     method, then calling the {@code hashCode} method on each of
     *     the two objects must produce the same integer result.
     * <li>It is <em>not</em> required that if two objects are unequal
     *     according to the {@link java.lang.Object#equals(java.lang.Object)}
     *     method, then calling the {@code hashCode} method on each of the
     *     two objects must produce distinct integer results.  However, the
     *     programmer should be aware that producing distinct integer results
     *     for unequal objects may improve the performance of hash tables.
     * </ul>
     * <p>
     * As much as is reasonably practical, the hashCode method defined by
     * class {@code Object} does return distinct integers for distinct
     * objects. (This is typically implemented by converting the internal
     * address of the object into an integer, but this implementation
     * technique is not required by the
     * Java&trade; programming language.)
     *
     * @return  a hash code value for this object.
     * @see     java.lang.Object#equals(java.lang.Object)
     * @see     java.lang.System#identityHashCode
     */
    public native int hashCode();
    public static void main(String[] args) {
        Object o = new Object();
        int hashcode = o.hashCode();
        System.out.println(hashcode);
    }
    输出:460141958

该方法返回一个对象的hashcode值。这是为了提高诸如java.util.HashMap中所提供的那些哈希表的性能。

  1. 在同一次的java程序应用过程中,对应同样的对象多次调用hashCode方法,hashCode方法必须一致性的返回同样的一个地址值,前提是这个对象不能改变
  2. 两个对象相同是依据equals方法来的,那么其中的每一个对象调用hashCode方法都必须返回相同的一个integer值,也就是对象的地址。equals方法相等,那么hashCode方法也必须相等。
  3. 如果两个对象依据equals方法返回的结果不相等,那么对于其中的每一个对象调用hashCode方法返回的结果也不是一定必须得相等(也就是说,equals方法的结果为false,那么hashCode方法返回的结果可以相同也可以不相同),但是,对于我们开发者来说,针对两个对象的不相等如果生成相同的hashCode则可以提高应用程序的性能。
 /**
     * Indicates whether some other object is "equal to" this one.
     * <p>
     * The {@code equals} method implements an equivalence relation
     * on non-null object references:
     * <ul>
     * <li>It is <i>reflexive</i>: for any non-null reference value
     *     {@code x}, {@code x.equals(x)} should return
     *     {@code true}.
     * <li>It is <i>symmetric</i>: for any non-null reference values
     *     {@code x} and {@code y}, {@code x.equals(y)}
     *     should return {@code true} if and only if
     *     {@code y.equals(x)} returns {@code true}.
     * <li>It is <i>transitive</i>: for any non-null reference values
     *     {@code x}, {@code y}, and {@code z}, if
     *     {@code x.equals(y)} returns {@code true} and
     *     {@code y.equals(z)} returns {@code true}, then
     *     {@code x.equals(z)} should return {@code true}.
     * <li>It is <i>consistent</i>: for any non-null reference values
     *     {@code x} and {@code y}, multiple invocations of
     *     {@code x.equals(y)} consistently return {@code true}
     *     or consistently return {@code false}, provided no
     *     information used in {@code equals} comparisons on the
     *     objects is modified.
     * <li>For any non-null reference value {@code x},
     *     {@code x.equals(null)} should return {@code false}.
     * </ul>
     * <p>
     * The {@code equals} method for class {@code Object} implements
     * the most discriminating possible equivalence relation on objects;
     * that is, for any non-null reference values {@code x} and
     * {@code y}, this method returns {@code true} if and only
     * if {@code x} and {@code y} refer to the same object
     * ({@code x == y} has the value {@code true}).
     * <p>
     * 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.
     *
     * @param   obj   the reference object with which to compare.
     * @return  {@code true} if this object is the same as the obj
     *          argument; {@code false} otherwise.
     * @see     #hashCode()
     * @see     java.util.HashMap
     */
    public boolean equals(Object obj) {
        return (this == obj);
    }
  1. 自反性 : x.equals(x) 结果应该返回true。
  2. 对称性 : x.equals(y) 结果返回true当且仅当y.equals(x)也应该返回true。
  3. 传递性 : x.equals(y) 返回true,并且y.equals(z) 返回true,那么x.equals(z) 也应该返回true。
  4. 一致性 : x.equals(y)的第一次调用为true,那么x.equals(y)的第二次,第三次等多次调用也应该为true,但是前提条件是在进行比较之前,x和y都没有被修改。
    x.equals(null) 应该返回false。
    这个方法返回true当且仅当x和y指向了同样的对象(x==y),这句话也就是说明了在默认情况下,Object类中的equals方法默认比较的是对象的地址,因为只有是相同的地址才会相等(x == y),如果没有重写equals方法,那么默认就是比较的是地址。
    注意:无论何时这个equals方法被重写那么都是有必要去重写hashCode方法,这个是因为为了维持hashCode的一种约定,相同的对象必须要有相同的hashCode值。
   /**
     * Creates and returns a copy of this object.  The precise meaning
     * of "copy" may depend on the class of the object. The general
     * intent is that, for any object {@code x}, the expression:
     * <blockquote>
     * <pre>
     * x.clone() != x</pre></blockquote>
     * will be true, and that the expression:
     * <blockquote>
     * <pre>
     * x.clone().getClass() == x.getClass()</pre></blockquote>
     * will be {@code true}, but these are not absolute requirements.
     * While it is typically the case that:
     * <blockquote>
     * <pre>
     * x.clone().equals(x)</pre></blockquote>
     * will be {@code true}, this is not an absolute requirement.
     * <p>
     * By convention, the returned object should be obtained by calling
     * {@code super.clone}.  If a class and all of its superclasses (except
     * {@code Object}) obey this convention, it will be the case that
     * {@code x.clone().getClass() == x.getClass()}.
     * <p>
     * By convention, the object returned by this method should be independent
     * of this object (which is being cloned).  To achieve this independence,
     * it may be necessary to modify one or more fields of the object returned
     * by {@code super.clone} before returning it.  Typically, this means
     * copying any mutable objects that comprise the internal "deep structure"
     * of the object being cloned and replacing the references to these
     * objects with references to the copies.  If a class contains only
     * primitive fields or references to immutable objects, then it is usually
     * the case that no fields in the object returned by {@code super.clone}
     * need to be modified.
     * <p>
     * The method {@code clone} for class {@code Object} performs a
     * specific cloning operation. First, if the class of this object does
     * not implement the interface {@code Cloneable}, then a
     * {@code CloneNotSupportedException} is thrown. Note that all arrays
     * are considered to implement the interface {@code Cloneable} and that
     * the return type of the {@code clone} method of an array type {@code T[]}
     * is {@code T[]} where T is any reference or primitive type.
     * Otherwise, this method creates a new instance of the class of this
     * object and initializes all its fields with exactly the contents of
     * the corresponding fields of this object, as if by assignment; the
     * contents of the fields are not themselves cloned. Thus, this method
     * performs a "shallow copy" of this object, not a "deep copy" operation.
     * <p>
     * The class {@code Object} does not itself implement the interface
     * {@code Cloneable}, so calling the {@code clone} method on an object
     * whose class is {@code Object} will result in throwing an
     * exception at run time.
     *
     * @return     a clone of this instance.
     * @throws  CloneNotSupportedException  if the object's class does not
     *               support the {@code Cloneable} interface. Subclasses
     *               that override the {@code clone} method can also
     *               throw this exception to indicate that an instance cannot
     *               be cloned.
     * @see java.lang.Cloneable
     */
    protected native Object clone() throws CloneNotSupportedException;

clone函数主要是用来进行对象的的克隆。在java当中,一个对象中的数据分为两种,一种是基本数据类型,另外一种是引用类型。那么为什么要克隆呢,是因为想得到一个对象的副本。通过重新创建出来一个赋值也是可以的。但是由于clone是一个native方法,那么执行的速度肯定是更快的。一个类如果能够使用clone方法应该要做到以下的几点:

  1. 对象的类实现Cloneable接口;
  2. 覆盖Object类的clone()方法 (覆盖clone()方法,访问修饰符设为public,默认是protected);
  3. 在clone()方法中调用super.clone();
    . 但是如果仅仅做到这些所复制出来的是钱拷贝,就是只能复制基本数据类型,引用类型和原来的那个还是指向的同一块地址。实现深拷贝和浅拷贝可以看这个:Object的clone方法测地剖析
  /**
     * Returns a string representation of the object. In general, the
     * {@code toString} method returns a string that
     * "textually represents" this object. The result should
     * be a concise but informative representation that is easy for a
     * person to read.
     * It is recommended that all subclasses override this method.
     * <p>
     * The {@code toString} method for class {@code Object}
     * returns a string consisting of the name of the class of which the
     * object is an instance, the at-sign character `{@code @}', and
     * the unsigned hexadecimal representation of the hash code of the
     * object. In other words, this method returns a string equal to the
     * value of:
     * <blockquote>
     * <pre>
     * getClass().getName() + '@' + Integer.toHexString(hashCode())
     * </pre></blockquote>
     *
     * @return  a string representation of the object.
     */
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

toString方法是我们很熟悉的一个方法了,如果我们不在自己的类中重载这个方法的话,那么他默认返回的是这个类的类名和hashcode值。

    /**
     * Wakes up a single thread that is waiting on this object's
     * monitor. If any threads are waiting on this object, one of them
     * is chosen to be awakened. The choice is arbitrary and occurs at
     * the discretion of the implementation. A thread waits on an object's
     * monitor by calling one of the {@code wait} methods.
     */
    public final native void notify();

	public final native void notifyAll();

这个方法和notifyAll要区分开,notify方法用于唤醒等待在该对象上的任意一个线程。
notifyAll方法用来唤醒所有的线程

   * Causes the current thread to wait until either another thread invokes the
     * {@link java.lang.Object#notify()} method or the
     * {@link java.lang.Object#notifyAll()} method for this object, or a
     * specified amount of time has elapsed.
public final native void wait(long timeout) throws InterruptedException;

public final void wait() throws InterruptedException {
        wait(0);
}
 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);
 }

这些方法在java并发编程里面都是讲过的。wait方法用来是当前线程阻塞在这个对象上,只有另外的线程调用了该对象的notify方法或者notifyAll方法,wait才能被唤醒。
可以看到,在OBject类中一个有三个重载的wait方法。其中只有一个方法是native方法。其他两个方法都只是调用了那个native方法。如果wait没有指定超时时间,那么就会传入超时时间是0.表示一直等待。若否则就等待超时时间,不然就会自动唤醒。

    /**
     * Called by the garbage collector on an object when garbage collection
     * determines that there are no more references to the object.
     * A subclass overrides the {@code finalize} method to dispose of
     * system resources or to perform other cleanup.
     */
	protected void finalize() throws Throwable { }

在java虚拟机当中已经学习过了。在java的GC中,若要宣布一个对象的死亡,需要经过两次标记过程。如果对象在第一次经过可达性分析之后,发现没有GC root相连接的引用链,那他将会被第一次标记,并进行一次筛选。筛选的条件就是此对象是否有必要执行finalize方法。当对象没有覆盖这个方法,或者说这个方法已经被执行过一次了,那么虚拟机都会认为这两种情况没有必要执行finalize。如果判定为有必要执行,那么这个方法会被放到一个对列中等待执行。这个方法是该对象逃脱被回收的最后一个方法。如果在该方法中该对象与其他任意一个对象建立联系,那么第二次标记就会将这个对象移除带回收对象的集合。不然他就会真正的被回收了。注意任何的finalize方法只会被执行一次,而且在java中这个方法并不被倡导使用。在JDK9之后就被淘汰了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值