35

我是如何阅读JDK源码的?

 3 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzU4NzYyMDE4MQ%3D%3D&%3Bmid=2247484325&%3Bidx=1&%3Bsn=7f9098033ef105be4a0d12da1a00554f
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1. 前言

之前断断续续读过一部分 JDK 常用类的源码,这里想把过程中的一些心得和方法记录下来,如果能帮到需要的小伙伴就再好不过了!

本文主要分享一下我的阅读工具和阅读顺序。

PS: 由于当前主流使用的 JDK 版本仍是 1.8,因此源码阅读主要是 1.8 版本,有些地方可以参考 1.7(面试可能问到)。

2. 工具

工欲善其事,必先利其器。

需要的工具不多,IDE + Google 翻译足够了。

使用 IDE 的主要目的是可以写一些测试代码以便跟踪调试。这个还是很有必要的,跟进代码的执行流程更容易理解它的实现原理。

直接在 IDE 打开源码文件,源码中的注释通常很详细,遇到不懂的地方 Google 翻译一下。也可以加上官方文档,其实源码里面注释跟文档是一样的,有些地方可能更详细,只不过官方文档排版更漂亮一些。

JDK 1.8 官方文档链接:https://docs.oracle.com/javase/8/docs/api/

当然,阅读的先后顺序也很重要,下面介绍下我的阅读顺序。

3. 阅读顺序

3.1 整体顺序

JDK 中的代码非常多,不可能、也没必要全部读完,因此要有的放矢。从整体上来讲,顺序大概是:

  1. 集合框架类

    1. 主要包括 Collection、Map、Queue 等组成的一系列常用类和接口,包括 ArrayList、LinkedList、HashMap 等。

    2. 这部分内容日常开发使用较多,而且面试高频出现,因此可以先从这里入手。

  2. 并发包

    1. 即 java.util.concurrent (J.U.C) 包下的常用类,包括 ReentrantLock、ThreadPoolExecutor、AQS 等。

    2. 该部分提供了并发编程的常用工具类,也是面试高频。

  3. 其他常用类

    1. 例如 ThreadLocal、String、StringBuilder、StringBuffer 等。

整体概览如下:

ryYzYnM.png!mobile

具体到某一个类,如何去阅读它的源码实现呢?下面继续介绍。

3.2 具体顺序

3.2.1 类和接口

如何阅读一个类的源码呢?主要步骤大概是:

  1. 先读接口代码。包括接口说明文档、各个方法的定义和说明文档。

  2. 再去读实现类的主要方法实现,通常有以下两条主线入口:

    1. 构造方法

    2. 常用方法

在 Java 中,接口通常意味着是一种“标准”、或者“协议”。一个接口可以有多个实现类,它们都会按照接口的这种标准来实现接口的各个方法。因此,理解了一个方法的定义,再去看它的实现会更容易理解。

下面以常用的 ArrayList 为例,分析如何去阅读它的源码。

3.2.2 ArrayList 源码分析

首先看下 ArrayList 的继承结构:

yqeQr2E.png!mobile

可以看到它实现了很多接口,其中三个接口 Cloneable、RandomAccess、Serializable 都是空的,可以暂时忽略。主要去看 Iterable、Collection 以及 List 接口的方法定义。

Iterable 接口:

FjYR73B.png!mobile

Collection 接口:

BnmE3aA.png!mobile

List 接口:

Yzyqqyz.png!mobile

看起来方法挺多,其实不少都是我们平时会用到的,大部分理解起来并不困难,而且方法也都有注释。这部分难度不大。

接下来根据前面提到的两条主线入口,分析 ArrayList 的源码如何阅读。

  • 构造器

分析一个类的源码时,构造器通常是一个好的切入点。比如 ArrayList 的三个构造器如下:

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

构造器中有不少成员变量,比如 elementData、EMPTY_ELEMENTDATA、DEFAULTCAPACITY_EMPTY_ELEMENTDATA 等,继续跟进这几个变量:

private static final Object[] EMPTY_ELEMENTDATA = {};

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

transient Object[] elementData; // non-private to simplify nested class access

由此可以得知,当我们写了 new ArrayList() 时,它的内部到底做了些什么。

  • 常用方法

除了构造器,常用方法也是一个主要的入口,比如 add、remove 等。

add 方法实现:

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

可以一行行跟进代码,查看 add 方法内部到底做了什么。

其他方法的套路也是如此,不再一一说明。

按照这样一条条主线走下来,就可以对 ArrayList 的实现原理有个整体的认知了。整体部分搞清楚之后,接下来还可以去读一些不太常用的方法,包括剩余的所有部分。

PS: 这里只是以常用的 ArrayList 为例,其他包下的类的阅读步骤也大同小异。

3.3 做笔记

此外,做笔记也很重要。

可以用思维导图梳理整体脉络,用笔记工具记录一个类的核心部分实现原理。

当然,如果自己整理和写出来笔记更好,许多时候总觉得自己知道了,但是别人一问就懵了,可能还是没理解到位吧。

有句话说得好:”教是最好的学“。当你能把某个知识点通俗易懂的讲给一个外行人,才是真的懂了。

3.4 注意点

刚开始读时,可能会遇到某些地方难以理解,可以尝试写测试代码断点跟踪调试,或者参考别人的博客。

如果遇到某个点实在难以理解,也可以先跳过,过段时间再重新思考也许就豁然开朗了。

PS:

  1. 以上内容纯属个人见解,仅供参考。

  2. 此外,我把之前文章的笔记整理成了电子书,后台回复「JDK源码」即可获取。

qEFbQjE.gif!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK