Java源碼分析之ArrayList

說(shuō)明一下,本次源碼是基于jdk1.8的厂榛。

我在了解寺渗,學(xué)習(xí)一個(gè)東西的時(shí)候,首先要了解清楚跟它有關(guān)的都有哪些東西扭倾,這些東西之間有著怎樣的關(guān)聯(lián)、結(jié)構(gòu)挽绩。所以膛壹,我會(huì)首先選擇從大處著眼,理清整個(gè)集合的層次關(guān)系唉堪,以及ArrayList它在整個(gè)集合的位置模聋。

從ArrayList這個(gè)類開(kāi)始,一層一層向上找唠亚,終于經(jīng)過(guò)一番不太愉快的努力之后撬槽,終于做出了一副圖(我就先將就著看吧)

ArrayList

從這幅奇丑無(wú)比的圖中,我們可以忍著痛暫時(shí)看出ArrayList集合在Collection這個(gè)框架中的一個(gè)層次趾撵。

接下來(lái)我要開(kāi)始庖丁解牛了侄柔,雖然刀法不怎么樣。

ArrayList的聲明:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

從聲明中占调,可以看到有泛型的存在暂题。泛型有一種較為正式的稱呼“參數(shù)化類型”,從“參數(shù)化”這個(gè)字面上去聯(lián)想究珊,就比較容易理解這個(gè)概念了薪者。一個(gè)函數(shù)聲明了它的調(diào)用參數(shù)之后,只要還沒(méi)有對(duì)這個(gè)函數(shù)進(jìn)行調(diào)用剿涮,那么它的參數(shù)的值也就沒(méi)有確定下來(lái)言津,只有當(dāng)調(diào)用了該函數(shù),傳遞了相應(yīng)的參數(shù)取试,其值才確定下來(lái)悬槽。以此類比,只有當(dāng)E的具體數(shù)據(jù)類型給定了瞬浓,這個(gè)泛型的類型才是真正確定了初婆。

看到泛型,我突然想到了在JVM中有一種叫“語(yǔ)法糖”的東西了猿棉。它不是糖磅叛,而且無(wú)色無(wú)味無(wú)實(shí)物,好吧其實(shí)就是一種語(yǔ)法萨赁。當(dāng)在java語(yǔ)言中使用了這種糖弊琴,在編譯期,會(huì)伴隨有類型擦除的動(dòng)作杖爽,即JVM會(huì)把當(dāng)初傳遞的類型參數(shù)給擦除掉敲董,再次變成Object(噢~紫皇,Object大法好!)臣缀,而在C++語(yǔ)言中則不會(huì)發(fā)生擦除動(dòng)作坝橡。所以相比來(lái)說(shuō),Java中的這種“語(yǔ)法糖”算是比較奇葩的精置。

不過(guò)話說(shuō)回來(lái)了计寇,既然最后還要把類型給擦除掉,可這種糖有什么用呢脂倦?肯定有用胺!那就是喂你吃赖阻,讓你開(kāi)心呀蝶押!什么意思?當(dāng)我們傳入了一個(gè)特定的參數(shù)類型后火欧,那么我們便可以放心地去向這個(gè)集合里面添加我們所需的元素棋电,即使失誤,添加了不對(duì)應(yīng)的類型苇侵,編譯器也會(huì)及時(shí)提醒我去做更改赶盔。反之,如果不傳入一個(gè)特定的類型參數(shù)榆浓,那么當(dāng)我們?cè)诰幊涕_(kāi)發(fā)的時(shí)候于未,什么時(shí)候腦子一熱,心里一興奮陡鹃,就把一個(gè)Integer烘浦,或者一個(gè)自定義類型的數(shù)據(jù)給放入進(jìn)去了。那么當(dāng)我們?cè)诒闅v該集合萍鲸,進(jìn)行類型轉(zhuǎn)換的時(shí)候闷叉,肯定是要出錯(cuò)的呀!同學(xué)們猿推,這個(gè)送分題可不能錯(cuò)捌啊!(嚴(yán)肅臉)

好蹬叭,回歸正題。接下來(lái)看一下ArrayList的屬性有哪些

private static final long serialVersionUID = 8683452581122892189L;

每一個(gè)可序列化的對(duì)象都要有這么一個(gè)serialVersionUID屬性值的状知。

private static final int DEFAULT_CAPACITY = 10;

ArrayList默認(rèn)的容量大小為10秽五!同學(xué)們,記住是10饥悴,又一道送分題坦喘!

private static final Object[] EMPTY_ELEMENTDATA = {};

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

transient Object[] elementData;

private int size;

接下來(lái)找一找ArrayList的構(gòu)造函數(shù)有哪些

//將elementData初始化為一個(gè)空的Object[]
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

空構(gòu)造函數(shù)盲再,ArrayList默認(rèn)容量為10;

    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
        //如果initialCapacity大于0瓣铣,則對(duì)Object[]類型的elementData進(jìn)行初始化
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
        //如果initialCapacity等于0答朋,則默認(rèn)初始化一個(gè)空的Object[]
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
        //否則拋錯(cuò)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

指定ArrayList容量:initialCapacity

    public ArrayList(Collection<? extends E> c) {
        //將Collection數(shù)組轉(zhuǎn)化為Object[]
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[](see 6260652)
            if (elementData.getClass() != Object[].class)
            //如果轉(zhuǎn)化的對(duì)象數(shù)組不是Object[]類型的,就利用Arryas工具類的copyOf方法來(lái)進(jìn)行一個(gè)強(qiáng)制轉(zhuǎn)化
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

傳入的參數(shù)為Collection<? extends E>類型棠笑,相當(dāng)于直接將Collection集合中的一部分?jǐn)?shù)據(jù)直接copy到了剛剛實(shí)例化的ArrayList集合中梦碗。注意工具類:Arrays的使用。

讀完了構(gòu)造函數(shù)蓖救,接下來(lái)再來(lái)看普通方法(遵循增刪改查的順序)

接下來(lái)說(shuō)一下ArrayList的添加對(duì)象方法

添加對(duì)象:

public boolean add(E e)

public void add(int index, E element)

public boolean addAll(Collection<? extends E> c)

public boolean addAll(int index, Collection<? extends E> c)

1.添加一個(gè)對(duì)象

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

該方法就是向ArrayList集合的末尾添加一個(gè)對(duì)象洪规,即調(diào)用elementData[size++] = e,ArrayList的增刪改差實(shí)際就是通過(guò)內(nèi)部的這個(gè)Object類型的數(shù)組來(lái)實(shí)現(xiàn)的循捺,沒(méi)錯(cuò)就是這么簡(jiǎn)單斩例。不過(guò)在增加之前還要再進(jìn)行一次容量的判斷,即判斷增加之后的數(shù)組大小和原來(lái)的數(shù)組大小从橘,如果原來(lái)數(shù)組大小偏小了念赶,則要進(jìn)行動(dòng)態(tài)擴(kuò)充,擴(kuò)充的原則則是恰力,oldSize *3/2,即oldSize的3/2

    public void add(int index, E element) {
        rangeCheckForAdd(index);
        // Increments modCount!!
        ensureCapacityInternal(size + 1);  
        System.arraycopy(elementData, index, elementData, index + 1, size - index);
        elementData[index] = element;
        size++;
    }

這個(gè)方法同樣也是增加一個(gè)對(duì)象叉谜,不過(guò)這個(gè)在指定位置出增加一個(gè)對(duì)象,所以該位置后面的所有對(duì)象都需要向后移動(dòng)一個(gè)位置牺勾,那么怎樣才能做到呢正罢?那就需要System.arraycopy()來(lái)幫忙啦。

    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

通過(guò)查看System類的源碼可對(duì)該方法有一個(gè)初步的了解了驻民。arraycopy為一個(gè)native方法翻具,所謂native方法是指首先該方法不是由Java來(lái)實(shí)現(xiàn)的,而是由其他偏底層的語(yǔ)言來(lái)實(shí)現(xiàn)的(比如C)回还,這樣通過(guò)調(diào)用這個(gè)方法裆泳,相比于非native方法來(lái)說(shuō),這類方法往往具有更高的效率柠硕。

這里有一篇英文文章來(lái)講解如何一步步來(lái)實(shí)現(xiàn)一個(gè)native method的

看完了native工禾,再來(lái)看一下五個(gè)參數(shù)。這個(gè)方法應(yīng)該是我到目前為止見(jiàn)到過(guò)參數(shù)最多的一個(gè)了蝗柔。通過(guò)參數(shù)的名字也不難理解它們各自的含義了闻葵,所以總的來(lái)說(shuō)這個(gè)方法的作用就是根據(jù)給定的一個(gè)數(shù)組和起始位置還有復(fù)制的長(zhǎng)度,來(lái)生成一個(gè)從指定位置復(fù)制后得到的對(duì)象癣丧。

另外再補(bǔ)充一個(gè)作用比較類似的方法:Arrays.copyof(T[] original, int newLength)

    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }

給定一個(gè)對(duì)象數(shù)組和長(zhǎng)度槽畔,將返回一個(gè)復(fù)制過(guò)的相應(yīng)長(zhǎng)度的對(duì)象數(shù)組

所以接著回上邊的add方法,經(jīng)過(guò)容量的檢測(cè)胁编,然后調(diào)用arraycopy方法來(lái)將原來(lái)index位置及其以后的元素全部增加一位重新復(fù)制到原來(lái)的數(shù)組中厢钧,最后在index位置處插入要增加的對(duì)象鳞尔。

    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        // Increments modCount
        ensureCapacityInternal(size + numNew);  
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

該addAll()方法將一個(gè)Collection類型的集合直接添加到ArrayList的后邊。
其中要涉及判斷容量是否需要擴(kuò)充早直,復(fù)制擴(kuò)充原來(lái)的數(shù)組寥假。

    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        Object[] a = c.toArray();
        int numNew = a.length;
        // Increments modCount
        ensureCapacityInternal(size + numNew);  
        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,numMoved);
        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }

該方法的作用是,在指定的位置處將一個(gè)Collection集合直接給插進(jìn)去霞扬。所以糕韧,既然有index索引位置參數(shù),所以要首先檢查是否訪問(wèn)越界祥得,檢測(cè)完正常之后兔沃,再去判斷是否要發(fā)生集合的擴(kuò)充,所以調(diào)用了ensureCapacityInternal()方法级及,最后再根據(jù)相應(yīng)的插入點(diǎn)位置來(lái)調(diào)用System.arraycopy方法來(lái)進(jìn)行一個(gè)數(shù)組的復(fù)制乒疏,即為插入之后的數(shù)組。

接下來(lái)說(shuō)一下ArrayList的刪除方法

刪除方法:

public E remove(int index)

public boolean remove(Object o)

private void fastRemove(int index)

public void clear()

第一個(gè)remove(int index)方法

    public E remove(int index) {
        rangeCheck(index);
        modCount++;
        E oldValue = elementData(index);
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
        return oldValue;
    }

經(jīng)過(guò)了上面對(duì)arraycopy方法的分析饮焦,發(fā)現(xiàn)這個(gè)remove(int index)突然變得如此的簡(jiǎn)單怕吴,只需要注意這個(gè)rangeCheck(index)邊界檢查的方法。

不過(guò)县踢,還需要注意變量modCount的變化转绷,每當(dāng)有刪除操作時(shí),該值就會(huì)+1硼啤,那么有什么用呢议经?這個(gè)在fail-fast機(jī)制中起到了一個(gè)提醒危險(xiǎn)的作用,至于具體是什么作用呢谴返?我也不會(huì)煞肾,可是我當(dāng)然會(huì)去搞懂它呢!

    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

如果index >= size,就會(huì)拋異常:IndexOutOfBoundsException

第二個(gè)remove(Object o)方法

public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

通過(guò)對(duì)集合進(jìn)行遍歷嗓袱,找到符合刪除對(duì)象的索引籍救,然后調(diào)用fastRemove(int index)方法來(lái)快速刪除該對(duì)象。

    private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

之所以叫做fastRemove渠抹,就是因?yàn)楫?dāng)他決定開(kāi)始刪除對(duì)象的時(shí)候蝙昙,就不用再進(jìn)行randCheck了,因?yàn)樵谕膺叺姆椒ㄖ幸呀?jīng)保證了index一定小于size梧却。

    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

該方法的作用為刪除一個(gè)指定集合奇颠。不過(guò)在刪除之前首先會(huì)判斷該集合是否為空,即調(diào)用了為 final類型的Objects.requireNonNull(T obj),其源碼如下:

    public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }

很簡(jiǎn)單的一段源碼放航,如果為空大刊,則拋NullPointerException()異常。接著再調(diào)用batchRemove方法三椿,其源碼如下:

 private boolean batchRemove(Collection<?> c, boolean complement) {
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;
        try {
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            if (r != size) {
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            if (w != size) {
                // clear to let GC do its work
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }

這段代碼的作用就是批量刪除一個(gè)Collection集合對(duì)象缺菌。(好吧,我承認(rèn)沒(méi)怎么看懂)

    public void clear() {
        modCount++;
        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;
        size = 0;
    }

調(diào)用clear()方法搜锰,簡(jiǎn)單粗暴地來(lái)清空整個(gè)集合伴郁。

接下來(lái)說(shuō)一下ArrayList的修改方法

修改方法:

public E set(int index, E element)

public void replaceAll(UnaryOperator<E> operator)

    public E set(int index, E element) {
        rangeCheck(index);
        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

該set()方法首先也會(huì)檢查index是否越界,如果沒(méi)有越界蛋叼,直接將index位置的對(duì)象替換即可焊傅,最后返回值為原來(lái)位置的那個(gè)對(duì)象。

    public void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final int expectedModCount = modCount;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            elementData[i] = operator.apply((E) elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

接下來(lái)說(shuō)一下ArrayList的查詢方法

修改方法:

public E get(int index)

public int indexOf(Object o)

public int lastIndexOf(Object o)

該方法的作用是替換一部分的對(duì)象狈涮,至于 UnaryOperator<E> 該類型之前沒(méi)有見(jiàn)過(guò)狐胎,沒(méi)有搞懂,所以這段代碼的分析暫時(shí)先擱置歌馍,隨后就來(lái)握巢,隨后就來(lái)

    public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }

該方法傳入一個(gè)位置索引參數(shù),返回相應(yīng)的類型松却。不過(guò)暴浦,在return之前,還需要調(diào)用兩個(gè)方法rangeCheck(index)和elementData(index)晓锻,

看一下和elementData()方法歌焦,這是一個(gè)私有方法,所以肯定是在該類內(nèi)部進(jìn)行服務(wù)的砚哆,從源碼里可以很容易看出独撇,就是檢查一下索引位置是否越界。

    @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

從源碼上很容易看出是獲得相應(yīng)索引值的對(duì)象躁锁,而且由于前邊由于已經(jīng)對(duì)邊界進(jìn)行檢查過(guò)了纷铣,所以此處可以加一個(gè)注解@SuppressWarnings來(lái)提示JVM忽略該方法可能所產(chǎn)生的警告。

    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

該方法的作用同樣是查灿里,不過(guò)這次返回的是指定對(duì)象的索引值关炼,其實(shí)內(nèi)部的原理很簡(jiǎn)單,就是對(duì)該集合進(jìn)行一個(gè)遍歷匣吊,如果找到了指定的Object對(duì)象儒拂,就返回該索引的值。

    public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size-1; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = size-1; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

同上面方法的原理幾乎一樣色鸳,這次是倒序查找社痛。

一些其他常見(jiàn)適用方法

    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

查詢是否包含指定對(duì)象

    public boolean isEmpty() {
        return size == 0;
    }

該集合是否為空

    public int size() {
        return size;
    }

返回該集合的大小

    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

將一個(gè)arrayList對(duì)象轉(zhuǎn)換成Object對(duì)象數(shù)組

至此,我想已經(jīng)將ArrayList的內(nèi)部實(shí)現(xiàn)的一些基本原理給寫(xiě)明白了命雀。希望這篇文章能夠幫到一些人蒜哀,同時(shí)也十分歡迎就一些疑問(wèn)或者想法直接留言進(jìn)行交流!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末吏砂,一起剝皮案震驚了整個(gè)濱河市撵儿,隨后出現(xiàn)的幾起案子乘客,更是在濱河造成了極大的恐慌,老刑警劉巖淀歇,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件易核,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡浪默,警方通過(guò)查閱死者的電腦和手機(jī)牡直,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)纳决,“玉大人碰逸,你說(shuō)我怎么就攤上這事±樱” “怎么了饵史?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)掸哑。 經(jīng)常有香客問(wèn)我约急,道長(zhǎng),這世上最難降的妖魔是什么苗分? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任厌蔽,我火速辦了婚禮,結(jié)果婚禮上摔癣,老公的妹妹穿的比我還像新娘奴饮。我一直安慰自己,他們只是感情好择浊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布戴卜。 她就那樣靜靜地躺著,像睡著了一般琢岩。 火紅的嫁衣襯著肌膚如雪投剥。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天担孔,我揣著相機(jī)與錄音江锨,去河邊找鬼。 笑死糕篇,一個(gè)胖子當(dāng)著我的面吹牛啄育,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拌消,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼挑豌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起氓英,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤侯勉,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后债蓝,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體壳鹤,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年饰迹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片余舶。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡啊鸭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出匿值,到底是詐尸還是另有隱情赠制,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布挟憔,位于F島的核電站钟些,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏绊谭。R本人自食惡果不足惜政恍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望达传。 院中可真熱鬧篙耗,春花似錦、人聲如沸宪赶。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)搂妻。三九已至蒙保,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間欲主,已是汗流浹背邓厕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留岛蚤,地道東北人邑狸。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像涤妒,于是被迫代替她去往敵國(guó)和親单雾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 一屿储、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對(duì)于byte類型而言...
    龍貓小爺閱讀 4,261評(píng)論 0 16
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法渐逃,內(nèi)部類的語(yǔ)法够掠,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法茄菊,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,631評(píng)論 18 399
  • java筆記第一天 == 和 equals ==比較的比較的是兩個(gè)變量的值是否相等疯潭,對(duì)于引用型變量表示的是兩個(gè)變量...
    jmychou閱讀 1,497評(píng)論 0 3
  • 接著Java集合框架學(xué)習(xí)---深入探究ArrayList源碼(一)繼續(xù)學(xué)習(xí)ArrayList源碼。 ensureC...
    EakonZhao閱讀 1,168評(píng)論 0 3
  • 如何變得富有面殖? By Derek Sivers Derek的建議很直接竖哩,是否認(rèn)同自己選擇。 1脊僚,住在好運(yùn)會(huì)降臨的地...
    霞光十色閱讀 255評(píng)論 4 1