欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Object源码阅读笔记

程序员文章站 2022-07-08 18:23:24
...

关于Object类,我们需要知道几点:

(1)Object类是Java中所有类的父类,在jdk9,它的位置位于java.base模块的java.lang包中。若用树形结构来描述Java类分类等级结构,则Object应该是树根root。

(2)Object类型的变量可以存储任意类型的引用(子类使用继承自Object的clone()时,要注意返回的副本对象的引用是Object类型,必须用Object类型的变量存储or进行类型转换),包括任意类型可以存储的null值,反之则不行。Object类型的变量创建时应注意先声明,事实上Java中所有类型的变量都需要先声明再使用。

Object obj;
System.out.println("obj: " + obj);
//没有声明会出错:可能尚未初始化变量

要判断某个引用是否属于某个类型,可以通过instanceof运算符。

https://mp.csdn.net/postedit/81952931

(3)利用第二点的特性可以用Object来给方法传参,以匹配更多类型的参数

class MyObject {
}

public class ObjectTest {
	public static void main(String[] args) {
		//paraType(null);  
        //错误:Exception in thread "main" java.lang.NullPointerException
		paraType(new Object());
		paraType(new MyObject());
	}
	public static void paraType(Object obj) {
		System.out.println(obj.getClass());
	}
}

注意:paraType(null)出现异常是因为Object的getClass()的调用者不能使空对象

 

Object类的内部成员如图所示,其中大部分为public、native修饰的方法。

Object源码阅读笔记

其中,两个protected方法没有实现,其他的都有;线程相关的方法以及getClass()不支持重写(自定义),其他的都支持

 

1、registerNatives()方法

private static native void registerNatives();   
    static {
        registerNatives();                          
    }
	//类首次加载时执行 
    //虚拟机调用initializeSystemClass方法,即静态初始化程序,来初始化静态变量、调用静态方法

2、Object()构造方法

public Object() {}

3、getClass()方法

    @HotSpotIntrinsicCandidate
    public final native Class<?> getClass();  
    // 用final修饰,说明不可被重写
    // 作用:返回对象的运行时类,返回的Class对象是被表示类的静态同步方法锁定的对象。
    // 这便于进行反射操作,进行动态加载指定的类等操作

Java中,每个类一般只加载一次。当程序编译成class文件之后,要运行时,class文件(从本地文件系统、网络、数据库)通过java.lang.ClassLoader类的class loader对象被加载到JVM——一个类对应一个class loader,可以扩展ClassLoader来得到我们想要的class loader,不过一般不这么做。然后它创建一个java.lang.Class<T>类型的对象,代表JVM中的T类的二进制表示。

Object类的getClass()返回Class类的一个对象的引用,而因为Object是所有类的父类,所以我们可以在任何类型的引用上调用这个方法。当我们在同个类型的多个引用上调用这个方法时,返回的是同一个Class类对象的引用。

注意:并不是所有类都在应用开始时被加载到JVM,只有当一个类被第一次使用时,才会被加载并产生相应的Class对象。

4、hashCode()方法

    /**
     * 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.
	 * 原则1:一致性————多次调用同一个对象的这个方法,返回的值一样
     *     This integer need not remain consistent from one execution of an
     *     application to another execution of the same application.
	 * 该整数不需要在 同一个应用的2次执行中 保持一致性
     * <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.
	 * 2、如果2个对象equals为true, 那么它们的hashCode为一样的值
     * <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.
	 * 3、不过如果2个对象equals为false, 那么hashCode也可能为一样的值
	 * 开发者应该注意:先使用hashCode进行筛选,可以提高哈希表的性能
     * </ul>
     * <p>
     * As much as is reasonably practical, the hashCode method defined
     * by class {@code Object} does return distinct integers for
     * distinct objects. (The hashCode may or may not be implemented
     * as some function of an object's memory address at some point
     * in time.)
	 * 4、尽可能合理地定义这个方法
	 * 有些类: 不同的对象(内存地址),哈希码不同;
	 * 有些类: 不同的内容, 哈希码不同
     * 根据我们的需要决定是否重写方法,有以上两种情况,不过不管是哪种情况,根据以上第二、三点,
     * 在使用时,(1)我们先用HashCode方法比较两个对象的哈希值是否相等,若不等,则一定不是同一个        
     * 对象or内容相同;反之,进第二步判断
     *(2)再用equals方法比较两个对象是否为同一个对象or内容是否相同,若返回结果为true,则同一个
     *对象or内容相同
     *之所以按照这个规则,我想大概基于两点:i、hashCode其实是将地址or内容采用一种算法进行映射得    
     *到一种编码,而equals则是直接比较两个对象的地址or内容是否相同。 所以,hashCode存在冲突的
     *现象————内容or地址不同的2个对象,hashCode值相同 ii、尽管equals是直接比较,但是其消耗较大
     *所以,先用hashCode有助于提高性能,筛选掉大部分情况(毕竟冲突时小概率事件)
     *
     * @return  a hash code value for this object.  
     * @see     java.lang.Object#equals(java.lang.Object)   对比equals
     * @see     java.lang.System#identityHashCode			对比identityHashCode
     */
    @HotSpotIntrinsicCandidate
    public native int hashCode();
    // 返回对象的哈希码(一个整数值)
	// 显然,本地的hashCode方法 比较的是内存地址(同一性)  重写的话另说
	// identityHashCode方法 用的是本地的hashCode方法 比较的是内存地址(同一性)
    //对于Object or String,注意前者的hashCode、equals、identityHashCode、==都是比较同一性
    //(地址),后者的hashCode、equals比较的是等同性(内容),System.identityHashCode、==补充
    //比较同一性(地址)    

5、equals()方法

/**
     * Indicates whether some other object is "equal to" this one.
     * <p>
     * The {@code equals} method implements an equivalence relation
     * on non-null object references:  注意是非空对象的等价关系,也就是说,null不能调用?
     * <ul>
     * <li>It is <i>reflexive</i>: for any non-null reference value
     *     {@code x}, {@code x.equals(x)} should return
     *     {@code true}.
	 * 性质1、反射性--任何 非空引用 调用自身,返回结果都是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}.
	 * 2、 对称性--两个引用 互相调用,返回结果一样
     * <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}.
	 * 3、 传递性
     * <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.
	 * 4、 一致性--两个对象之间的调用  多少次还是那个结果   前提是没有信息被修改
     * <li>For any non-null reference value {@code x},
     *     {@code x.equals(null)} should return {@code false}.
	 * 5、 任意非空引用 调用null   返回的都是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}).
	 * Object的equals实现: 最具有辨别力(其hashCode可能会有冲突的现象)的2个
	 *非空引用 的等价性比较
	 *也就是说,只有x,y都是同一个对象的引用时(指向同一个对象),返回的才是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.
	 * 不管equals方法有没有重写,我们都要重写hashCode方法
	 *从而保证————equal的对象(无重写:内存地址相同,指向同一个对象;有重写:内容相同)
     *具有相同的hashCode值:for 地址or 内容的各个位 + hashCode算法 ==得到 相同的值
     * @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  看看HashMap中的实现原理:基于HashCode()  重复元素
     */
    public boolean equals(Object obj) {
        return (this == obj);   // 比较的是两个对象的内存地址 
		// 前面总是说reference object,也就是引用型数据,而不是基本类型数据(比较简单)
        //基本数据类型一般都是用 ==
    }

6、Clone()方法

/**
     * 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>
	 * (1)clone方法是产生对象的一个独立副本 
     * 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.
	 * (2)对象x和它clone的独立副本 调用getClass方法 结果一样
     * While it is typically the case that:
	 * 但这些不是绝对的条件(意思是clone可以重写吗?)
     * <blockquote>
     * <pre>
     * x.clone().equals(x)</pre></blockquote>
     * will be {@code true}, this is not an absolute requirement.
	 * x的clone副本 和 自己 equal  但是不是绝对的(意思是如果equal的是地址的话就不一定?)
     * <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()}.
	 * 按照惯例,返回的对象应该通过super.clone调用得到
	 *如果一个类和它所有父类遵循这个惯例,那么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.
	 *按照惯例,返回的对象是独立的
	 *为了实现这个独立性,返回副本之前 有必要修改这个对象的一个or多个元素
	 *通常,这意味着复制组成这个对象深层结构的所有可变元素,并用副本的引用替换这些元素的引用
	 *如果一个类只包含原始字段、不可变元素的引用,那么super.clone返回的对象 没有字段需要修改
	 *大概意思: 浅拷贝  只复制引用的值,没有复制可变元素所引用的对象
     * <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.
	 *Object的clone方法实施具体的操作:
	 *1、如果这个对象的类 没有实现Cloneable接口, CloneNotSupportedException异常就会抛出
	 *2、注意所有arrays 应该实现Cloneable接口 T[]返回T[] T是任意引用、基本类型
	 *3、否则,此方法初始化这个对象的新对象+赋值所有字段(但字段的内容不会被克隆)
	 *这也就是浅拷贝,而不是深拷贝操作
	 *4、Object类自己并没有实现Cloneable接口,因此在Object类的对象上调用方法,运行时会抛出异常
     *
     * @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.
	 * 当对象的类不支持Cloneable接口时,抛出异常
	 * 重写这个方法的子类 也可以抛出这个异常(以表示这个实例不能被克隆)
     * @see java.lang.Cloneable     对比Cloneable
     */
    @HotSpotIntrinsicCandidate
    protected native Object clone() throws CloneNotSupportedException;
    //1、一般在原型模式时使用
    //2、使用时需要让被拷贝的对象所属的类实现Cloneable接口,才能调用该方法进行拷贝。

7、toString()方法

/**
     * 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:
	 *返回的字符串包括:类的名字、@、对象的16进制表示的哈希值
     * <blockquote>
     * <pre>
     * getClass().getName() + '@' + Integer.toHexString(hashCode())
	 *类的名字、@、对象的16进制表示的哈希值
     * </pre></blockquote>
     *
     * @return  a string representation of the object.
     */
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    // 用于显示该对象的内容
    // 一般需要重写

8、notify()方法

/**
     * 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.
	 *唤醒在这个对象的监视器上的 一个等待线程
	 *如果有线程在等待队列中等待(通过调用wait方法,一个线程在对象的监视器上等待),其中的一个
	 *被选中唤醒。这种选择是任意的,根据算法进行竞争(最着急的线程)
	 *
     * <p>
     * The awakened thread will not be able to proceed until the current
     * thread relinquishes the lock on this object. The awakened thread will
     * compete in the usual manner with any other threads that might be
     * actively competing to synchronize on this object; for example, the
     * awakened thread enjoys no reliable privilege or disadvantage in being
     * the next thread to lock this object.
	 *唤醒的线程将无法继续(被其他对象使用?在等待) 直到当前线程放弃对这个对象的锁定
	 *被唤醒的线程 以通用的方式 与任何其他(积极竞争同步这个对象的)线程竞争
     *同步,是说没有特权,都有机会成为能够锁定该对象的线程
     * <p>
     * This method should only be called by a thread that is the owner
     * of this object's monitor. A thread becomes the owner of the
     * object's monitor in one of three ways:
	 *这个方法只能被一个线程(这个线程是 对象的监视器的所有者)调用
	 *一个线程可以以3种方式 成为这个对象的监视器的所有者
     * <ul>
     * <li>By executing a synchronized instance method of that object.
     * <li>By executing the body of a {@code synchronized} statement
     *     that synchronizes on the object.
     * <li>For objects of type {@code Class,} by executing a
     *     synchronized static method of that class.
     * 1、在调用notify()之前,线程必须获得该对象的对象级别锁 
     * 2、执行完notify()方法后,不会马上释放锁,要直到退出synchronized代码块,当前线程才会释放
     *锁  
     * 3、notify()一次只随机通知一个线程进行唤醒
     * </ul>
     * <p>
     * Only one thread at a time can own an object's monitor.
	 *原则:一次只能有一个线程 拥有一个对象的监视器
     *
     * @throws  IllegalMonitorStateException  if the current thread is not
     *               the owner of this object's monitor.
	 *如果当前线程 不是这个对象的monitor的所有者,抛出IllegalMonitorStateException
     * @see        java.lang.Object#notifyAll()  对比notifyAll
     * @see        java.lang.Object#wait()       对比wait
     */
    @HotSpotIntrinsicCandidate
    public final native void notify();
    //唤醒对象的等待队列上的 一个线程

9、notifyAll()方法

    public final native void notifyAll();
    //唤醒所有 等待在这个对象的监视器上的线程

10、wait()方法

//第一种实现:使线程进入等待状态,直到被notify or notifyAll调用 or 等待时间达到限定值
//timeout - 要等待的最长时间(以毫秒为单位)。
//nanos - 额外时间(以毫微秒为单位,范围是 0-999999)
//超时时间=1000000*timeout+nanos(毫微秒)。
    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);
    }

//实现二:使线程进入等待状态,直到被notify or notifyAll调用
    public final void wait() throws InterruptedException {
        wait(0);
    }

11、finalize()方法

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

从Java SE 9开始弃用 

 

关于native方法

JDK源代码由C++、Java、C、汇编 这四种语言组成。JVM主体是C++写的,JNI部分是C,工具类是Java写的,JVM里混有汇编代码。JNI是Java Native Interface的缩写,从Java 1.1 开始,Java Native Interface (JNI)标准就成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。

"A native method is a Java method whose implementation is provided by non-java code"。一个Native Method是这样的一个java方法:该方法的实现由非java语言实现,比如C。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数。

Native方法:

https://blog.csdn.net/wike163/article/details/6635321

Native方法的使用示例:

https://www.cnblogs.com/HDK2016/p/7226840.html

blog.51cto.com/2301703/1035358

Native方法的内部细节:

wiki.jikexueyuan.com/project/jni-ndk-developer-guide/serchnative.html

https://juejin.im/post/59634a666fb9a06bbf6ffce6