【干貨】用大白話聊聊JavaSE — ArrayList 深入剖析和Java基礎知識詳解(一)

Paste_Image.png

對Java程序開發而言,ArrayList 的使用頻率是非常高的,尤其在進行 JavaWeb 開發的時候,ArrayList 和 HashMap 這兩個類,相信你一定不會陌生,因為天天都在用嘛。

本系列對 ArrayList 做一個解析,同時把Java基礎知識個串連進去。一開始我會對如何使用 ArrayList 做一個簡要的說明,然后,我們來仿照 ArrayList 封裝一個自己的集合框架MyList,通過練習,來一步一步猜想ArrayList 可能的實現方式。

最后,深入到ArrayList 的源碼進行解讀。

為什么要學習源碼?

很簡單,一個知道源碼的人和一個不知道源碼的人,雖然都能使用 ArrayList ,但是,他們在使用的時候,心態是完全不一樣的。

只有當你深入了源碼,然后你才會對它的一些細節有更充分的認識。這是一本萬利的事情。

當然,對于初學者,還是盡量以使用為主,因為源碼的話,畢竟有一定的難度。如果一味地追求這些東西,可能會大大降低自己的學習興趣和熱情。

1、 ArrayList 概述


副本難度:一顆星
經驗值:500



首先來看一下文檔,

Paste_Image.png

<h5>
All Implemented Interfaces:
Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
</h5>

<p>
從圖中可以看到,ArrayList 實現了Iterable接口,這個接口表示一種迭代的能力。
</p>

既然是ArrayList,那么肯定和 List 有關,所以它果然繼承了List接口。

接口的知識點在這里就用上了。

其他接口我們暫且不談,先繼續。

然后,我們看一下官方對ArrayList 做出的說明。

文檔中有這么一句:

Resizable-array implementation of the List interface.

這句話是說,ArrayList 是對List接口的一個實現,實現方式是利用一個可改變尺寸的數組,也就是說,它的底層就是一個數組。而且是可改變尺寸的數組,說明這個數組是動態的。

哦,難怪它叫ArrayList ,Array就是數組的意思,那么它肯定和數組有關。

**Implements all optional list operations, and permits all elements, including null. **

ArrayList 實現了list接口的所有方法,并且允許空元素。

前半句是肯定的,因為在Java中,如果一個類實現了一個接口,那么就必須要重寫該接口里所有的抽象方法。

我們知道,接口里只有方法的聲明,沒有方法的實現。

我對接口的理解,總結以后就只有一句話:

Java類實現接口,就是給這個類本身添加了一個新的身份。

ArrayList是一個類,那么它的身份就是ArrayList,你問他“你叫什么名字呀?”,他肯定會毫不猶豫地告訴你,“我叫ArrayList!”。

白天,我們大家都以為它是ArrayList,結果到了夜晚。

ArrayList竟然搖身一變,成為了Iterable!

原來,ArrayList實現了Iterable,所以它也就擁有了Iterable的身份。

接口其實就是這個意思。網上對接口的解釋眾說紛紜,反正我總結下來就是這么一句話,也不想搞那么復雜了。

ArrayList不僅有Iterable的身份,還擁有其他好幾種身份,比如List,Collection等。

這個情況也叫作多態。

新建一個測試類。

public class TestArrayList1 {

    public static void main(String[] args) {
        
    }
}

現在我新建一個ArrayList類的實例

ArrayList list = new ArrayList();

這肯定是沒問題的。

文檔上說,ArrayList 實現了Iterable接口,那么也就是說,它的另一個身份是Iterable。

所以,我這樣寫是不是也沒有問題啊。

Iterable iterable = new ArrayList();

就好像白天是普通的上班族,一旦到了夜晚,就。。。

總之,

Iterable iterable = new ArrayList();

這句話的含義就是說,它原來是普通的ArrayList,一旦情況需要,就變身成為Iterable。

好了,既然變成了 Iterable ,那么它是不是也就擁有了 Iterable 的能力?

我們來看一下 Iterable 有哪些方法?

去除繼承自Object類的方法不談,Iterable 只有一個方法,就是 iterator()

Paste_Image.png

它返回的是一個 Iterator ,這是一個迭代器。

通過這個迭代器,我們是不是就可以遍歷 ArrayList 中所有的數據了呀?

首先,我們需要一個迭代對象:

Iterable iterable = new ArrayList();
Iterator it = iterable.iterator();

當然,這個例子中,ArrayList里面沒有數據。

現在思考一個問題,是不是我非得把 ArrayList 對象改變成 Iterable 身份,才可以調用 iterator() 方法呢?

當然不是了,ArrayList 有一個身份是 Iterable ,所以它具有 Iterable 的所有能力(方法),這沒問題。那么難道 ArrayList 不變身,就沒有 Iterable 的能力了嗎?

答案自然是否定的。

一個小說家如果有一天轉行去寫代碼了,那么你覺得他還會不會寫小說呢?

肯定會嘛,這沒有什么好懷疑的。

所以,代碼這么寫是不是也沒關系?

ArrayList list = new ArrayList();

for (int i = 0; i < 100; i++) {
    list.add(i);
}

Iterator it = list.iterator();

循環輸出

while(it.hasNext()){
    System.out.println(it.next());
}
Paste_Image.png

總結一下,ArrayList 它只要實現 Iterable 接口,那么它就必須要擁有 Iterable 規定的所有能力,也就是方法。而接口中,我們知道它里面只有方法的聲明,沒有方法的實現,所以 ArrayList 需要實現這些方法,實現接口就是這么個意思。

2、 ArrayList常用方法


副本難度:三顆星
經驗值:800

2.1、 屬性和方法的調用問題

在調用ArrayList的方法之前,我們需要先獲得一下ArrayList的實例對象,除了靜態方法,其他所有的方法,都只能由對象來調用。

ArrayList是一個類,我更愿意把它稱為一個** 數據模板**。它只是一個模板而已,不是一個實實在在的對象,這一點首先要確定。

就好像工廠生產一個產品,首先是不是要有一個模板和設計圖紙,這個模板決定了你這個產品是一種怎樣的形狀,以及可能會具備哪些功能?圖紙則決定了功能的具體實現。

比如生成一部手機,模板開出來就是一個扁平的長方體的樣子,可是光有模板還不行,你還得規定它的一些具體細節。

這些細節就好比是Java類的構造方法,以及其他的一些方法實現。

但是,你光給客戶模板和圖紙行嗎?

一般來說是不行的。

至于靜態方法,我們知道,我們調用靜態方法的時候,不需要先生成一個實例,可以通過類名直接調用。

這就相當于,在弄模版的時候,這些功能就已經定制在里面了。

你買手機的時候,里面不是經常有一些內置的應用嗎?有些刪都刪不掉,這不就相當于靜態方法嗎?

(我只是舉一個例子啊,你不要非得較真說我可以ROOT一下啊)

如果模板里面已經有了一些做好的功能,今后任何根據這個模具生成出來的產品也自帶了這些功能。

如果模板里面已經做好了一些功能,那么我的確可以使用這個模板,而不需要真正拿到一個產品。

比如生產一部手機,它的模板里面已經做好了一個手電筒的功能,那么,你即便不給我一個真正的產品,僅僅給我一個模板,我是不是也可以用它的手電筒功能呢?

這就是靜態方法。

所以我們常說,靜態方法和靜態屬性為所有實例共用,不就是這個道理嗎?

所以,正常情況下,我們調用一個類的非靜態方法,是不是必須要先new一個對象?

好的,我們現在來 根據 ArrayList 模板生產一個 ArrayList 產品

這樣,我們才能調用它里面所有的非私有方法。

怎么生產呢,是不是new一下就可以啦?

ArrayList  arrayList = new ArrayList(); 

2.2、 add方法

ArrayList是一個集合,既然是一個集合,那么它肯定是可以往里頭添東西的。

怎么往里面添,用add,用add方法往里面加。

arrayList.add("HelloWorld"); //添加一個字符串
arrayList.add(new Integer(100));//添加一個Integer類型的數字

add的參數就是一個object,這就是多態,多態就是多種形態,多種身份的意思。object可以有多種形態。它可以是String,也可以是Integer,還可以是用戶自定義的類型。

這里是不是又多態了。。。

這就是多態的一個用法。

2.3、 get 方法

既然能夠往里面添加東西,是不是肯定還要拿出來啊。

怎么拿出來,用get方法拿出來,而且一次只能拿一個。不要多拿哦。

get 方法需要傳入一個 int 類型的數字,這個數字就是元素對應的下標。

我們剛才第一個放進去的是 "HelloWorld" ,一個字符串。那么對應的下標就是0 。

第二個放進去的是new Integer(100),這是一個Integer對象,是一個實實在在的東西了。那么對應的下標就是1 。

現在,我取出第1個元素,應該是100。

試試看

Integer i = arrayList.get(1);
Paste_Image.png

報錯了,因為 get 方法返回的是一個Object對象,而我們拿Integer 去接,就出問題了。

這是咋回事呢?

很簡單,比如張三是一個醫生,同時他還擁有一個人類的身份,可并不是所有的人類都是醫生啊?

注意我下面分析的用詞,能幫助你理解。

同理,Integer 是一個整數類型,同時它還擁有一個Object的身份,可并不是所有的 Object 都是Integer 啊?

同接口一樣,A繼承B,可以看成A同時擁有了B的身份。

如果A繼續保持A的身份,那么它不僅擁有自己本身的能力,也擁有B的能力。只要A愿意,他完全可以展現B的能力。

如果A變身成為了B,那么它肯定不希望別人知道他是A。

就好比雖然他知道他可以變身成為奧特曼,但是一般情況下,他都不愿意曝露自己的身份。

所以如果A變身成為了B,那么A就只會使用B的能力,同時隱藏他本身的能力。

如果你是初學者,請仔細體會一下這其中的韻味。慢慢地,你就會對多態有一個更深入的理解。一段時間后,你再重新去看以前寫的代碼,會有不一樣的感覺。

再舉一個例子,幫助你理解。

我 new 一個 ArrayList :(在eclipse中)

ArrayList  arrayList = new ArrayList();

換行,寫上arrayList 。

我直接在arrayList 右邊加一個點,然后會有提示:

Paste_Image.png

這些都是它可以調用的方法和屬性,哇,這么多。

如果我這樣寫呢?

Object  arrayList = new ArrayList();

我也在arrayList 右邊加一個點

Paste_Image.png

不好意思,你現在只能調用 Object 類的屬性和方法了。

嗯,再體會一下。

初學者在面向對象方面的理解總是會走彎路,如果你能把這些東西理清,對今后的學習會有巨大的好處。

繼續。

我們這里就強轉一下吧,因為我們知道 index 為1的元素是一個Integer類型的。

Integer i = (Integer) arrayList.get(1);
System.out.println(i);

結果

Paste_Image.png

好的,是正確的。

2.4、 remove 方法

remove 方法可以刪除集合中的元素,ArrayList給我們提供了很多刪除元素的方法。

Paste_Image.png

我們這里先看一下第一個方法。

這是通過數組下標來刪除某一個特定的元素,我們剛才給ArrayList添加了兩個元素,下標分別為 0,1 ,那么,如果我刪除第0個元素,會怎么樣呢?

首先,ArrayList的列表長度會不會改變?

我們可以通過size()方法來獲取ArrayList當前的列表長度。

測試:

arrayList.remove(0);
System.out.println(arrayList.size());

打印出來是1,看來的確是影響長度了。

2.5、 toArray 方法

這個方法可以將ArrayList轉換成一個Object數組。

例:

Object[] objs = arrayList.toArray();

for (int i = 0; i < objs.length; i++) {
    System.out.println(objs[i].toString());
}

需要注意的是,哪怕你給ArrayList全部添加Integer類型的元素,也不能采用這樣的代碼:

Integer[] objs = (Integer[]) arrayList.toArray();

這是錯誤的,雖然編譯的時候不會報錯,但是運行無法通過。

因為ArrayList的add方法可以添加任意類型的參數,Java運行機制無法獲知ArrayList中的元素是否可以都強制轉換為你指定的類型。所以這種寫法是不被允許的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容