目錄
? ? 1 Java基礎(chǔ)
? ? 2 Java集合
? ? 3 Java多線程
? ? 4 JVM
? ? 5 常見問題匯總參考資料
? ? ·《Java編程思想》
? ? ·《Java Web 技術(shù)內(nèi)幕》
? ? ·《Java 并發(fā)編程實(shí)戰(zhàn)》
1 Java基礎(chǔ)
1.1 對象
1.1.1 創(chuàng)建對象
1.1.1.1 引用
????用引用(reference)操縱對象。猶如遙控器和電視機(jī)的關(guān)系。
1.1.1.2 new關(guān)鍵字
????創(chuàng)建對象,并存儲(chǔ)在堆heap中。
1.1.1.3 特例:基本類型
(1)基本類型與包裝類
? ? ? ? · 裝箱過程是通過調(diào)用valueOf方法(Integer Integer.valueOf(int))實(shí)現(xiàn)的,拆箱為xxxValue()(int Integer.intValue())。
? ? ? ? · Integer裝箱時(shí),在[-128, 127]之間不創(chuàng)建新對象,否則創(chuàng)建新對象。
? ? ? ? · Integer、Short、Byte、Character、Long類似。Double、Float裝箱類似,每次創(chuàng)建新對象。
? ? ? ? ·?當(dāng) "=="運(yùn)算符的兩個(gè)操作數(shù)都是 包裝器類型的引用,則是比較指向的是否是同一個(gè)對象,而如果其中有一個(gè)操作數(shù)是表達(dá)式(即包含算術(shù)運(yùn)算)則比較的是數(shù)值(即會(huì)觸發(fā)自動(dòng)拆箱的過程)。另外,對于包裝器類型,equals方法并不會(huì)進(jìn)行類型轉(zhuǎn)換。
demo:
public class Main {
????public static void main(String[] args) {
????????Integer a = 1;
????????Integer b = 2;
????????Integer c = 3;
????????Integer d = 3;
????????Integer e = 321;
????????Integer f = 321;
????????Long g = 3L;
????????Long h = 2L;
????????System.out.println(c==d);
????????System.out.println(e==f);
????????System.out.println(c==(a+b));
????????System.out.println(c.equals(a+b));
????????System.out.println(g==(a+b));
????????System.out.println(g.equals(a+b));
????????System.out.println(g.equals(a+h));
????}
}
true? ?false? ? true? ? true? ?true? ? false? ? ?true
第一個(gè)和第二個(gè)輸出結(jié)果沒有什么疑問。第三句由于? a+b包含了算術(shù)運(yùn)算,因此會(huì)觸發(fā)自動(dòng)拆箱過程(會(huì)調(diào)用intValue方法),因此它們比較的是數(shù)值是否相等。而對于c.equals(a+b)會(huì)先觸發(fā)自動(dòng)拆箱過程,再觸發(fā)自動(dòng)裝箱過程,也就是說a+b,會(huì)先各自調(diào)用intValue方法,得到了加法運(yùn)算后的數(shù)值之后,便調(diào)用Integer.valueOf方法,再進(jìn)行equals比較。同理對于后面的也是這樣,不過要注意倒數(shù)第二個(gè)和最后一個(gè)輸出的結(jié)果(如果數(shù)值是int類型的,裝箱過程調(diào)用的是Integer.valueOf;如果是long類型的,裝箱調(diào)用的Long.valueOf方法)。
(2)存儲(chǔ)位置:堆棧
(3)8中基本類型的字節(jié)大小。

1.1.2 不需要手動(dòng)銷毀對象
? ? · 作用域:花括號(hào)決定
? ? · GC機(jī)制決定不需要手動(dòng)銷毀對象。
1.1.3 類
(1)成員變量(字段)、成員函數(shù)(方法)。其中對于基本類型的成員變量有默認(rèn)值。
(2)Java程序:
? ? ? ? · 無“向前引用”問題
? ? ? ? · 通配符 *,import java.lang.*
? ? ? ? · static 修飾時(shí),屬于類屬性,與實(shí)例無關(guān)。
? ? ? ? · java.lang 在程序中被自動(dòng)導(dǎo)入。
? ? ? ? · 編碼風(fēng)格:命名規(guī)則采用“駝峰命名法”。類名的首字母要大寫;如果類名由幾個(gè)單詞構(gòu)成,則并在一起,每個(gè)內(nèi)部單詞的首字母采用大寫;方法、字段以及對象引用名稱等與類相似,只是這些標(biāo)識(shí)符的第一個(gè)字母采用小寫。
1.1.4 對象的構(gòu)成
Java的對象頭和對象組成詳解_Clarence-CSDN博客
1.2 操作符
1.2.1 關(guān)系操作符
? ? “==”與equals()區(qū)別:
? ? · ==對基本類型來說比較數(shù)值,對引用類型來說比較的是內(nèi)存地址。
? ? · equals()在沒有被覆蓋時(shí),等價(jià)于“==”。當(dāng)被覆蓋時(shí),一般比較的是對象的內(nèi)容。
? ? · String對象中的equals()方法被覆蓋過了,比較的是內(nèi)容。
1.2.2 按位操作符
? ? 非(~)不能用于布爾類型,可用!(邏輯操作符)。
1.2.3 移位符
? ? · >>> “無符號(hào)”右移
? ? · char、byte、short 移位前需要轉(zhuǎn)int類型
1.2.4 字符串操作
? ? String中的“+”操作符底層原理:
? ? ? ? new StringBuffer(str).append(c).toString();
1.2.5 類型轉(zhuǎn)換(cast)
· 基本數(shù)據(jù)類型
? ? · 窄化轉(zhuǎn)換(危險(xiǎn))
? ? · 擴(kuò)展轉(zhuǎn)換(安全)
1.3 控制執(zhí)行
????foreach 用于數(shù)組和容器
? ? ? ? ? ? · 任何一個(gè)返回?cái)?shù)組的方法 for(String str : getString()){ }
? ? ? ? ? ? · 任何Iterable對象
1.4 初始化與清理
1.4.1 構(gòu)造器
? ? 如果已經(jīng)定義了一個(gè)構(gòu)造器(有/無參),編譯器不會(huì)自動(dòng)創(chuàng)建默認(rèn)構(gòu)造器,此時(shí)調(diào)用默認(rèn)無參構(gòu)造器報(bào)錯(cuò)。
1.4.2 方法重載
? ? 同一個(gè)類中,方法名相同,參數(shù)的類型、個(gè)數(shù)、順序不同。
1.4.3 this
? ? · 獲得當(dāng)前對象的引用
? ? · 只能在方法內(nèi)部使用
? ? · 構(gòu)造器之間調(diào)用時(shí),this 只能最多有一個(gè),且只能放第一行
? ? · 不能再staitc修飾的方法中調(diào)用
1.4.4 終結(jié)處理與垃圾回收
1.4.4.1 finalize()方法
(1)finalize()方法是Object類中提供的一個(gè)方法,在GC準(zhǔn)備釋放對象所占用的內(nèi)存空間之前,它將首先調(diào)用finalize()方法。其在Object中定義如下:protected void finalize() throws Throwable { }
(2)finalize()調(diào)用的時(shí)機(jī)
????????與C++的析構(gòu)函數(shù)(對象在清除之前析構(gòu)函數(shù)會(huì)被調(diào)用)不同,在Java中,由于GC的自動(dòng)回收機(jī)制,因而并不能保證finalize方法會(huì)被及時(shí)地執(zhí)行(垃圾對象的回收時(shí)機(jī)具有不確定性),也不能保證它們會(huì)被執(zhí)行(程序由始至終都未觸發(fā)垃圾回收)。
public class Finalizer {
????@Override
????protected void finalize() throws Throwable {
????????System.out.println("Finalizer-->finalize()");
????}
????public static void main(String[] args) {
????????Finalizer f = new Finalizer();
????????f = null;
????}
}
//無輸出
public class Finalizer {
????@Override
????protected void finalize() throws Throwable {
????????System.out.println("Finalizer-->finalize()");
????}
????public static void main(String[] args) {
????????Finalizer f = new Finalizer();
????????f = null;
????????System.gc();//手動(dòng)請求gc
????}
}
//輸出 Finalizer-->finalize()
(3)?什么時(shí)候應(yīng)該使用它
????finalize()方法中一般用于釋放非Java 資源(如打開的文件資源、數(shù)據(jù)庫連接等),或是調(diào)用非Java方法(native方法)時(shí)分配的內(nèi)存(比如C語言的malloc()系列函數(shù))。
(4)為什么避免使用
????首先,由于finalize()方法的調(diào)用時(shí)機(jī)具有不確定性,從一個(gè)對象變得不可到達(dá)開始,到finalize()方法被執(zhí)行,所花費(fèi)的時(shí)間這段時(shí)間是任意長的。我們并不能依賴finalize()方法能及時(shí)的回收占用的資源,可能出現(xiàn)的情況是在我們耗盡資源之前,gc卻仍未觸發(fā),因而通常的做法是提供顯示的close()方法供客戶端手動(dòng)調(diào)用。
????另外,重寫finalize()方法意味著延長了回收對象時(shí)需要進(jìn)行更多的操作,從而延長了對象回收的時(shí)間。
1.4.4.2 顯示GC( system.gc() )也不一定執(zhí)行
1.4.4.3 GC算法
(1) 引用計(jì)數(shù)
? ? ? ? ? ? 描述工作方式,未實(shí)現(xiàn)。
(2)復(fù)制
(3)標(biāo)記清除
(4)標(biāo)記整理
(5)分代收集機(jī)制
? ? ? ? · 新生代(使用復(fù)制算法)
? ? ? ? · 老年代(使用標(biāo)記清除和標(biāo)記整理算法)
1.4.5 初始化順序
(1)字段在任何方法(包括構(gòu)造器)之前得到初始化。
(2)static
? ? ? ? · 只有在必要時(shí)刻才會(huì)進(jìn)行(訪問該類,因?yàn)閟taic修飾屬于類屬性)
? ? ? ? · 代碼塊加載順序
? ? ? ? ? ? 靜態(tài)代碼塊(類加載的時(shí)候加載一次)---> 普通代碼塊(在實(shí)例化時(shí)加載,可加載多次)---> 構(gòu)造函數(shù)(先調(diào)用父類構(gòu)造函數(shù))
1.5 訪問控制
(1)每個(gè).java文件只能包含一個(gè)public類
(2)訪問權(quán)限修飾詞
? ? ? ? ? ? · 包訪問權(quán)限(默認(rèn))
? ? ? ? ? ? · public 對每個(gè)人可見
? ? ? ? ? ? · private 僅該類可見(子類可以通過set、get方法調(diào)用private屬性),不可修飾類
? ? ? ? ? ? · protected 繼承的子類可見? 不可修飾類
? ? ? ? ? ? · 將構(gòu)造函數(shù)用private修飾,可以做成單例模式。
// 利用private修飾構(gòu)造器,完成單例模式
Class Demo {
? ? private Demo(){};
? ? private static Demo p = new Demo();
? ? public static Demo access(){
? ? ? ? return p;
????}
}
1.6 復(fù)用類
1.6.1 組合類
? ? 在類的字段中包含對其他類的引用。
1.6.2 繼承
? ? 所有類都隱式繼承Object類。
? ? Object類的方法:

? ? · 關(guān)于clone方法:Java 淺拷貝和深拷貝 - 簡書、java中clone方法的理解(深拷貝、淺拷貝)_xinghuo0007的博客-CSDN博客
(1)語法
? ? ? ? · 父類中,成員變量用private,成員方法用public
? ? ? ? · 使用extends關(guān)鍵字
? ? ? ? · 使用super.function()在覆蓋的方法中訪問父類方法。
(2)初始化
? ? ? ? · 子類沒有構(gòu)造器,調(diào)用父類的
? ? ? ? · 基類先加載。基類在導(dǎo)出類構(gòu)造器可以訪問它之前,就已經(jīng)完成初始化。
(3)覆蓋(復(fù)寫)
? ? ? ? · 重載基類的方法,基類本身的方法并不會(huì)被屏蔽。
? ? ? ? · 只想覆蓋 @override注解(不加注解,基類的方法依然存在)
(4)向上轉(zhuǎn)型
1.6.3 final
(1)數(shù)據(jù)
? ? ? ? · 編譯時(shí)常量,無法創(chuàng)建setter方法
? ? ? ? · 運(yùn)行時(shí)初始化并不變
? ? ? ? · 使用前總被初始化
(2)方法
? ? ? ? 防止繼承類修改。(private 隱式在子類中指定為final)
(3)類
? ? ? ? 不可被繼承,所有方法隱式為final
1.6.4 初始化及加載
(1)有基類,先加載
(2)加載static
(3)new 先加載基類構(gòu)造器,再加載子類構(gòu)造器。
1.7 多態(tài)
? ? 面向?qū)ο蟮娜筇卣鳎悍庋b、繼承、多態(tài)。
1.7.1 方法調(diào)用綁定
(1)前期綁定:在程序編譯期間綁定
(2)后期綁定:在運(yùn)行時(shí)綁定(動(dòng)態(tài)綁定),static方法不具有多態(tài)。
1.7.2 多態(tài)設(shè)計(jì)
? ? · 繼承
? ? · 組合:通過類似set方法,修改成員變量
? ? · 接口
1.7.3 向上轉(zhuǎn)型(安全)
1.8 接口
? ? 提供了一種將接口和實(shí)現(xiàn)分離的方法。
1.8.1 抽象類
(1)包含抽象方法的類 abstract
? ? ? ? 可以含有構(gòu)造方法,子類實(shí)例化時(shí),先調(diào)用父類構(gòu)造器。
(2)繼承
? ? ? ? · 子類必須實(shí)現(xiàn)抽象方法
? ? ? ? · 可以繼續(xù)使用abstact修飾,可以不用實(shí)現(xiàn)抽象方法
(3)不需要所有方法都是抽象
(4)不可以實(shí)例化
1.8.2 接口interface
(1)所以方法都抽象,且隱式為public的
(2)可以包含域,隱式為static和final的
(3)實(shí)現(xiàn):子類實(shí)現(xiàn)所有接口方法 implements
(4)不可以實(shí)例化
1.8.3 多重繼承
(1)extends 一個(gè)基類 implements 多個(gè)接口
(2)接口之間可以使用extends繼承
(3)可以向上轉(zhuǎn)型為任意接口
1.8.4 設(shè)計(jì)模式
(1)策略設(shè)計(jì)模式:根據(jù)所傳參對象不同,具有不同方法(重載)
(2)適配器設(shè)計(jì)模式:接受擁有的接口,產(chǎn)生所需要的對象
(3)工廠方法設(shè)計(jì)模式:返回接口的某個(gè)實(shí)現(xiàn)的對象
1.9 異常處理
(1)基本異常Exception
? ? ? ? · new 異常對象
? ? ? ? · 異常參數(shù):
? ? ? ? ? ? ? ? · 默認(rèn)構(gòu)造器
? ? ? ? ? ? ? ? · 字符串
(2)捕獲異常
? ? ? ? · try
? ? ? ? · catch
? ? ? ? ? ? 異常處理的結(jié)果有終止模型和恢復(fù)模型兩種。Java支持終止模型,認(rèn)為錯(cuò)誤非常關(guān)鍵,以至于程序無法返回到異常發(fā)生的地方繼續(xù)執(zhí)行,一旦異常被拋出,就表明錯(cuò)誤已無法挽回,也不能回來繼續(xù)執(zhí)行。
? ? ? ? · finally
? ? ? ? ? ? ? ? · 作用:把內(nèi)存之外的資源恢復(fù)到初始狀態(tài),如已經(jīng)打開的文件或者網(wǎng)絡(luò)等。
? ? ? ? ? ? ? ? · 含有return時(shí),覆蓋其他return。
(3)自定義異常:extends Exception 異?;?/p>
(4)異常說明 throws
(5)發(fā)送異常時(shí)的清理:在創(chuàng)建需要清理的對象之后,立即進(jìn)入try-catch-fianlly(嵌套)
(6)java.lang.Throwable

? ? ? ? · Error(錯(cuò)誤):是程序無法處理的錯(cuò)誤,表示運(yùn)行應(yīng)用程序中較嚴(yán)重問題。編譯時(shí)和系統(tǒng)錯(cuò)誤。
? ? ? ? · Exception(異常):是程序本身可以處理的異常。可以被拋出的異常。
1.10 字符串
1.10.1 String對象不可變
? ? 定義:private final byte/char value[] (byte定義是JDK1.9出現(xiàn)的)
字符串與常量池的關(guān)系:Java提高篇之常量池_#include-CSDN博客
1.10.2? “+”“+=”的重載
? ? ? ? · java中僅有的兩個(gè)重載過的操作符
? ? ? ? · “+”底層用了StringBuffer()的append()和toString()方法。
1.10.3 正則表達(dá)式
(1)創(chuàng)建正則 java.util.regex.Pattern
(2)表達(dá)式
? ? ? ? · \\\\ 普通的反斜線
? ? ? ? · \\d 一個(gè)數(shù)字
? ? ? ? · split( regex )
? ? ? ? · replaceAll(regx,String)
正則表達(dá)式參考:Java正則表達(dá)式
1.10.4 對比
(1)StringBuilder
? ? ? ? · extends AbstractStringBuilder,不用final修飾
? ? ? ? · 線程不安全
(2)StringBuffer
? ? ? ? · extends AbstractStringBuilder
? ? ? ? · 線程安全,對方法加同步鎖
(3)常用方法:append、insert、indexOf、toString()
1.11 類型信息
1.11.1 RTTI
? ? ? ? 運(yùn)行時(shí)類型識(shí)別。
? ? (1)“傳統(tǒng)”,假定在編譯時(shí)知道了所有類型
? ? (2)“反射”,在運(yùn)行時(shí)發(fā)現(xiàn)和使用類的信息
1.11.2 Class對象
? ? java.lang.Class類
(1)被編譯后產(chǎn)生,保存在.class文件中
(2)用來創(chuàng)建類的所有對象。創(chuàng)建前,用類加載器加載Class對象
(3)獲取Class對象的方式:
? ? ? ? · Class c1 = Class.forName(“類的全限定名”);
? ? ? ? · Class c2 = 類名.class;
? ? ? ? · Class c3 = this.getClass();
1.11.3 RTTI應(yīng)用場景
(1)類型轉(zhuǎn)換
(2)class對象
(3)instance of
(4)反射
? ? ????class類與java.lang.reflect類庫
(5)JDK動(dòng)態(tài)代理
? ? ? ? Proxy.newProxyInstance(類加載器,接口列表(目標(biāo)接口),InvocationHandler實(shí)例)
1.12 IO
1.12.1 分類
(1)基于字節(jié)操作:InputStream/OutputStream
? ? ? ? 數(shù)據(jù)持久化或者網(wǎng)絡(luò)傳輸都是以字節(jié)進(jìn)行的。
(2)基于字符操作:Reader/Writer
(3)基于磁盤操作:File
(4)基于網(wǎng)絡(luò)操作:Socket
? ? InputStreamReader從字節(jié)到字符轉(zhuǎn)化,需要制定字符集
????OutputStreamWriter從字符到字節(jié)轉(zhuǎn)化
字符和字節(jié)的區(qū)別:字節(jié)與字符的區(qū)別 | 菜鳥教程
1.12.2 模式
(1)BIO
? ? ? ? · 同步阻塞
? ? ? ? · 面向流
? ? ? ? · 數(shù)據(jù)讀取阻塞在線程中
(2)NIO
? ? ? ? · 同步非阻塞
? ? ? ? · 面向緩沖、基于通道,有選擇器
? ? ? ? · channel、selector、Buffer
(3)AIO
? ? ? ? · 異步非阻塞
? ? ? ? · 基于事件和回調(diào)機(jī)制
1.12.3 磁盤IO工作模式
(1)調(diào)用方式
? ? ? ? ?讀取和寫入文件IO操作都調(diào)用操作系統(tǒng)提供的接口,因?yàn)榇疟P設(shè)備是由操作系統(tǒng)管理的。
? ? 系統(tǒng)調(diào)用read()/write() ----》內(nèi)核空間(含緩存機(jī)制) -----》用戶空間
(2)訪問文件方式
? ? · 標(biāo)準(zhǔn)訪問文件方式:先查緩存,再查磁盤。write()時(shí),內(nèi)核緩存同步sync時(shí)間由操作系統(tǒng)決定。

? ? · 直接IO: 不經(jīng)過內(nèi)核空間

? ? · 同步訪問文件:數(shù)據(jù)寫到磁盤才返回成功標(biāo)志給應(yīng)用程序。

? ? · 異步訪問文件:不阻塞等待

1.12.4 Java序列化技術(shù)
? ? (1)java序列化技術(shù)就是將一個(gè)對象轉(zhuǎn)化成一串二進(jìn)制表示的字節(jié)數(shù)組,通過保存或轉(zhuǎn)移這些字節(jié)數(shù)據(jù)來達(dá)到持久化的目的。
? ? (2)對象必須繼承java.io.Serializable接口。
? ? (3)反序列化時(shí),必須有原始類作為模板,才能將這個(gè)對象還原。
1.12.5 NIO
1.12.5.1 簡介
????Java NIO(New IO)是一個(gè)可以替代標(biāo)準(zhǔn)Java IO API的IO API(從Java 1.4開始),Java NIO提供了與標(biāo)準(zhǔn)IO不同的IO工作方式。
· Java NIO: Channels and Buffers(通道和緩沖區(qū))
????????標(biāo)準(zhǔn)的IO基于字節(jié)流和字符流進(jìn)行操作的,而NIO是基于通道(Channel)和緩沖區(qū)(Buffer)進(jìn)行操作,數(shù)據(jù)總是從通道讀取到緩沖區(qū)中,或者從緩沖區(qū)寫入到通道中。
· Java NIO: Non-blocking IO(非阻塞IO)
????????Java NIO可以讓你非阻塞的使用IO,例如:當(dāng)線程從通道讀取數(shù)據(jù)到緩沖區(qū)時(shí),線程還是可以進(jìn)行其他事情。當(dāng)數(shù)據(jù)被寫入到緩沖區(qū)時(shí),線程可以繼續(xù)處理它。從緩沖區(qū)寫入通道也類似。
· Java NIO: Selectors(選擇器)
????????Java NIO引入了選擇器的概念,選擇器用于監(jiān)聽多個(gè)通道的事件(比如:連接打開,數(shù)據(jù)到達(dá))。因此,單個(gè)的線程可以監(jiān)聽多個(gè)數(shù)據(jù)通道。


1.12.5.2?Buffers緩沖區(qū)
(1)java.nio包中定義對基本類型的容器。
Buffer就像一個(gè)數(shù)組,可以保存多個(gè)相同類型的數(shù)據(jù)。根據(jù)類型不同(boolean除外),有以下Buffer常用子類:
? ? ·ByteBuffer
? ? ·CharBuffer
? ? ·ShortBuffer
? ? ·IntBuffer
? ? ·LongBuffer
? ? ·FloatBuffer
? ? ·DoubleBuffer
(2)屬性
? ? ? ? ·容量(capacity):表示Buffer最大數(shù)據(jù)容量,緩沖區(qū)容量不能為負(fù),并且建立后不能修改。
? ? ? ? ·限制(limit):第一個(gè)不應(yīng)該讀取或者寫入的數(shù)據(jù)的索引,即位于limit后的數(shù)據(jù)不可以讀寫。緩沖區(qū)的限制不能為負(fù),并且不能大于其容量(capacity)。
? ? ? ? ·位置(position):下一個(gè)要讀取或?qū)懭氲臄?shù)據(jù)的索引。緩沖區(qū)的位置不能為負(fù),并且不能大于其限制(limit)。
? ? ? ? ·標(biāo)記(mark)與重置(reset):標(biāo)記是一個(gè)索引,通過Buffer中的mark()方法指定Buffer中一個(gè)特定的position,之后可以通過調(diào)用reset()方法恢復(fù)到這個(gè)position。
(3)分類
? ? · 非直接緩沖區(qū):通過allocate() 方法分配緩沖區(qū),將緩沖區(qū)建立在 JVM 的內(nèi)存中。數(shù)據(jù)存儲(chǔ)傳輸需要先復(fù)制到內(nèi)存地址空間,再到磁盤。

? ? · 直接緩沖區(qū):
? ? ? ? ·通過allocateDirect() 方法分配直接緩沖區(qū),將緩沖區(qū)建立在物理內(nèi)存中。可以提高效率。
? ? ? ? · 也可以通過FileChannel 的 map() 方法 將文件區(qū)域直接映射到內(nèi)存中來創(chuàng)建。

1.12.5.3 Channels通道
(1)作用
????????表示打開到IO 設(shè)備(例如:文件、套接字)的連接。若需要使用NIO 系統(tǒng),需要獲取用于連接 IO 設(shè)備的通道以及用于容納數(shù)據(jù)的緩沖區(qū)。然后操作緩沖區(qū),對數(shù)據(jù)進(jìn)行處理。Channel 負(fù)責(zé)傳輸, Buffer 負(fù)責(zé)存儲(chǔ)。
(2)java.nio.channels.Channel 接口:
? ? ? ? ·FileChannel
? ? ? ? ·SocketChannel
? ? ? ? ·ServerSocketChannel
? ? ? ? ·DatagramChannel
(3)分散讀取、聚集寫入
? ??????????scattering Reads:將通道中的數(shù)據(jù)分散到多個(gè)緩沖區(qū)中。
? ??????????gathering Writes:將多個(gè)緩沖區(qū)的數(shù)據(jù)聚集到通道中

1.12.5.4 阻塞與非阻塞
(1)阻塞:客戶端連接請求時(shí),服務(wù)器只能等待連接請求,不能處理其他事情。
(2)非阻塞:客戶端連接注冊到多路復(fù)用器上,當(dāng)輪詢到連接有I/O請求時(shí),才啟動(dòng)線程處理。
(3)幾種IO模式的線程之間對比
????BIO:同步阻塞式IO,服務(wù)器實(shí)現(xiàn)模式為一個(gè)連接一個(gè)線程,即客戶端有連接請求時(shí)服務(wù)器端就需要啟動(dòng)一個(gè)線程進(jìn)行處理,如果這個(gè)連接不做任何事情會(huì)造成不必要的線程開銷,當(dāng)然可以通過線程池機(jī)制改善。?
????NIO:同步非阻塞式IO,服務(wù)器實(shí)現(xiàn)模式為一個(gè)請求一個(gè)線程,即客戶端發(fā)送的連接請求都會(huì)注冊到多路復(fù)用器上,多路復(fù)用器輪詢到連接有I/O請求時(shí)才啟動(dòng)一個(gè)線程進(jìn)行處理。?
????AIO(NIO.2):異步非阻塞式IO,服務(wù)器實(shí)現(xiàn)模式為一個(gè)有效請求一個(gè)線程,客戶端的I/O請求都是由OS先完成了再通知服務(wù)器應(yīng)用去啟動(dòng)線程進(jìn)行處理。?
? ? 偽異步:使用線程池管理

1.12.5.5 Selector選擇器
(1)SelectionKey類
????在SelectionKey類的源碼中我們可以看到如下的4中屬性,四個(gè)變量用來表示四種不同類型的事件:可讀、可寫、可連接、可接受連接
? ? ? ? ·SelectionKey.OP_CONNECT
? ? ? ? ·SelectionKey.OP_ACCEPT
? ? ? ? ·SelectionKey.OP_READ
? ? ? ? ·SelectionKey.OP_WRITE
????如果你對不止一種事件感興趣,那么可以用“位或”操作符將常量連接起來,如下:
????????int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;

1.12.5.6 NIO的Socket請求

? ? 分為兩個(gè)線程共工作,一個(gè)監(jiān)聽客戶端連接,一個(gè)用于處理數(shù)據(jù)交互。
1.13 JPA
(1)Java Persistence API 持久層API
? ??????JPA僅僅是一種規(guī)范,也就是說JPA僅僅定義了一些接口,而接口是需要實(shí)現(xiàn)才能工作的。所以底層需要某種實(shí)現(xiàn)
(2)基于O/R映射的標(biāo)準(zhǔn)規(guī)范
(3)主要實(shí)現(xiàn):Hibernate、EclipseLink、openJPA
(4)提供
? ? ? ? · XML或注解,將實(shí)體對象持久化到數(shù)據(jù)庫中。@Entity、@Table、@Column、@Transient
? ? ? ? · API,用來操作實(shí)體對象,執(zhí)行CRUD
? ? ? ? · JPQL查詢語句
(5)避免字段持久化到數(shù)據(jù)庫方法
? ? ? ? · static?java序列化之-static|transient 修飾的字段能否被序列化?_CD-CSDN博客
? ? ? ? · final
? ? ? ? · transient 也可以在Java中修飾,防止序列化。
? ? ? ? · @Transient
2 Java集合
2.1 泛型
? ? 指定容器可以保存的類型,在編譯器檢查錯(cuò)誤。
2.2 分類
? ? Java容器類類庫的用途是“保存對象”。
2.2.1 Collection
? ? · Collection容器繼承了Iterable接口( 實(shí)現(xiàn)iterator()方法 ),都可以使用foreach。
? ? · Collection容器都覆蓋了toString(),可以直接使用print()
2.2.1.1 List表
(1)必須按照插入的順序保存元素
(2)常見接口方法
? ? · boolean add(E e); 在尾部追加元素? ? ? ? · void add(int index, E element)?
?????· void clear()????????????????????????????????????????????· boolean contains(Object o)? ? ? ? ? ? ? ? ??
? ? ?· E get(int index);獲取指定下標(biāo)的元素? ? · int indexOf(Object o)獲取指定元素的下標(biāo)
? ? ?· boolean isEmpty() 判斷是否為空? ? ? ? ? · E remove(int index / Object o) 移除? ? ? ? ? ? ? ? ? ?
? ? ?· E set(int index, E element) 修改元素? ? · int size() 獲得大小? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ?· Object[] toArray[] 轉(zhuǎn)化為數(shù)組
2.2.1.2 Set
(1)不能用重復(fù)元素
(2)常見接口方法
? ? · boolean add(E e)? ? ? ? · void clear()? ? ?· boolean contains(Object o)
? ? · boolean isEmpty()? ? ? ?· boolean remove(Object o)? ? ? ?· int size()
? ? · Object[] toArray()
2.2.1.3 Queue
(1)按照排隊(duì)規(guī)則來確定對象產(chǎn)生的順序
(2)@常見接口方法
? ? · Throws exception
? ? ? ? · boolean add(E e)? ? ? · E remove()?返回并刪除頭元素? ? ? · E element() 返回頭元素
? ? · Returns special value
? ? ? ? · boolean offer(E e)? ? ? · E poll() 返回并彈出頭節(jié)點(diǎn)? ? ? ? ? ? · E peek() 返回頭元素
2.2.2 Map
(1)一組成對的“鍵值對”對象,允許使用鍵來查找值
(2)常見接口方法
? ? · void clear()? ? ? ? ? · boolean containsKey(Object key)? ? ?
? ? · boolean containsValue(Object value)? ?· Set<Map.Entry<K,V>> entrySet()? ? ? ??
????· boolean equals(Object o)? ? ? ? ? ? ? ? ? ? ?· Object get(Object key)
? ? · boolean isEmpty()? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? · Object put(Object k, Object v)?會(huì)覆蓋前面的值? ? ? ?
????· Object remove(Object key)
????· default boolean replace(Object key, Object value, Object newValue)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
????· int size()? ? ? ? · remove(Object key)????
? ? ·?getOrDefault(Object key, V defaultValue)
? ? 說明:
? ? ? ? 調(diào)用Map.entrySet(),將集合中的映射關(guān)系對象存儲(chǔ)Set中。迭代Set集合,通過entry的getKey()和getValue()方法獲取映射關(guān)系對象。
2.3 迭代器Iterator
2.3.1 概念
? ? · 迭代器是一個(gè)對象,它的工作是遍歷并選擇序列中的對象,而客戶端程序員不必知道或關(guān)心該序列底層的結(jié)構(gòu)。
? ? · 迭代器只能單向移動(dòng)。
? ? · 不能對正在被迭代的集合進(jìn)行結(jié)構(gòu)上的改變,否則拋出異常。但可以使用iterator自己的remove方法
2.3.2 使用
(1)使用iterator()返回一個(gè)Iterator對象,并準(zhǔn)備返回序列的第一個(gè)元素。
(2)使用next()獲得序列的下一個(gè)元素
(3)使用hasNext()檢查序列中是否還有元素
(4)使用remove()將迭代器新近返回的元素刪除
public class Demo{
? ? public static void mian(String[] args){
? ? ? ? List<Pet> pets = Pets.arrayList(12);
? ? ? ? Iterator<Pet> it = pets.iteratror();
? ? ? ? while(it.hasNext()){
? ? ? ? ? ? Pet p = it.next();
? ??????????system.out.print(p);
????????}
? ? ? ? for(Pet p : pets){
? ? ? ? ? ? system.out.print(p);
????????}? ? }
}
使用foreach語法更簡潔。
2.4 List的實(shí)現(xiàn)
2.4.1 ArrayList
2.4.1.1 基本特性
(1)擅長于隨機(jī)訪問元素,但插入和移除元素慢
(2)線程不安全,底層為Object數(shù)組
2.4.1.2 擴(kuò)容機(jī)制
(1)無參構(gòu)造時(shí),初始為空數(shù)組。當(dāng)添加第一個(gè)元素時(shí),擴(kuò)為10(默認(rèn))。
(2)填滿時(shí),自動(dòng)擴(kuò)容,變?yōu)樵瓉淼?.5倍左右(奇數(shù)偶數(shù)不同)。
2.4.2 LinkedList
(1)插入刪除代價(jià)較低,但隨即訪問慢。
(2)線程不安全,底層為雙向鏈表。
(3)沒有實(shí)現(xiàn)RandomAccess接口(標(biāo)識(shí)是否具有隨機(jī)訪問能力)。
(4)實(shí)現(xiàn)了基本的List接口,同時(shí)添加了可以使用其作棧、隊(duì)列或者雙端隊(duì)列的方法。
2.4.3 Vector
(1)Vector簡介
Vector 是矢量隊(duì)列,它是JDK1.0版本添加的類。繼承于AbstractList,實(shí)現(xiàn)了List, RandomAccess, Cloneable這些接口。
Vector 繼承了AbstractList,實(shí)現(xiàn)了List;所以,它是一個(gè)隊(duì)列,支持相關(guān)的添加、刪除、修改、遍歷等功能。
Vector 實(shí)現(xiàn)了RandmoAccess接口,即提供了隨機(jī)訪問功能。RandmoAccess是java中用來被List實(shí)現(xiàn),為List提供快速訪問功能的。在Vector中,我們即可以通過元素的序號(hào)快速獲取元素對象;這就是快速隨機(jī)訪問。
Vector 實(shí)現(xiàn)了Cloneable接口,即實(shí)現(xiàn)clone()函數(shù)。它能被克隆。
和ArrayList不同,Vector中的操作是線程安全的。
(2)底層分析
? ? ?·Vector實(shí)際上是通過一個(gè)數(shù)組去保存數(shù)據(jù)的。當(dāng)我們構(gòu)造Vecotr時(shí);若使用默認(rèn)構(gòu)造函數(shù),則Vector的默認(rèn)容量大小是10。
? ? ?·當(dāng)Vector容量不足以容納全部元素時(shí),Vector的容量會(huì)增加。若容量增加系數(shù) >0,則將容量的值增加“容量增加系數(shù)”;否則,將容量大小增加一倍。
? ? ?·Vector的克隆函數(shù),即是將全部元素克隆到一個(gè)數(shù)組中。
2.5 Stack棧
? ? (1)后進(jìn)先出(LIFO)的容器,是限制插入和刪除只能在一個(gè)位置上進(jìn)行的表。
? ? (2)LinkedList作為底層實(shí)現(xiàn)。
? ? (3)常用方法:
? ? ? ? · push(Object o)? ? ? ? ? ? ? ? ? ? ? ? · pop()? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? · peek()
????(4)常見應(yīng)用:
? ? ? ? ? ? · 后綴表達(dá)式
2.6 Set的實(shí)現(xiàn)
2.6.1 HashSet
(1)最快的獲取元素的方式
(2)利用HashMap的Key存儲(chǔ)
(3)判斷重復(fù)元素原理:
? ? ? ? · 利用hashCode()和equals()方法。先計(jì)算加入對象的hashcode值來判斷加入的位置,同時(shí)與其他對象的hashcode值比較,如果沒有相同的hashcode,則假設(shè)對象沒有重復(fù)出現(xiàn)。若hashcode相同,則通過equals方法價(jià)差hashcode相等的對象是否真的相同,若相同,則插入操作不成功;若不同,則重新散列。
? ? ? ? · equals()方法被覆蓋,則hashCode()方法也必須被覆蓋。原因:
? ? ? ? ? ? ? ? · 兩個(gè)對象相等,hashcode值一定相同。
? ? ? ? ? ? ? ? · 兩個(gè)對象相等,equals()方法放回true。
? ? ? ? ? ? ? ? · 相同hashcode值,對象不一定相等。
2.6.2 TreeSet
(1)具有有序的存儲(chǔ)順序,按照比較結(jié)果的升序保存對象
(2)利用紅黑樹結(jié)構(gòu)實(shí)現(xiàn)
2.6.3 LinkedHashSet
(1)按照添加的順序保存對象
(2)使用鏈表來維護(hù)元素的插入順序
2.7 Map的實(shí)現(xiàn)
2.7.1 HashMap
2.7.1.1 概念
(1)提供最快的查找技術(shù)
(2)基于散列表實(shí)現(xiàn)
(3)線程不安全
(4)hash()方法
static final int hash(Object key) {
????int h;
????// key.hashCode():返回散列值也就是hashcode
????// ^ :按位異或
????// >>>:?符號(hào)右移,忽略符號(hào)位,空位都以0補(bǔ)?
????return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
? ? · HashMap通過key的hashCode經(jīng)過擾動(dòng)函數(shù)處理過后得到hash值
? ? · 然后通過(n - 1) & hash判斷當(dāng)前元素存放的位置,n為數(shù)組的長度。
? ? · 判斷該元素與存入的元素的hash值和key是否相同,相同則直接覆蓋,不相同就通過“拉鏈法”解決沖突。
2.7.1.2 底層數(shù)據(jù)結(jié)構(gòu)
(1)JDK1.8之前,使用數(shù)組+鏈表
? ? ? ? 數(shù)組中存儲(chǔ)Node<K,V>(implements Map.Entry<K,V>)。數(shù)組初始大小為16.

(2)JDK1.8之后,使用數(shù)組+鏈表+紅黑樹,當(dāng)鏈表的長度大于閾值(默認(rèn)8)時(shí) ,變?yōu)榧t黑樹

2.7.1.3 rehash擴(kuò)容機(jī)制
(1)哈希桶數(shù)組table的長度length大小必須為2的n次方(一定是合數(shù)),這是一種非常規(guī)的設(shè)計(jì),常規(guī)的設(shè)計(jì)是把桶的大小設(shè)計(jì)為素?cái)?shù)。相對來說素?cái)?shù)導(dǎo)致沖突的概率要小于合數(shù)
為什么要是2的n次方:取余(%)操作中,如果除數(shù)是2的冪次則等價(jià)于其除數(shù)減一的與(
&)操作,即hash%length == hash & (length - 1)。采用二進(jìn)制的位操作后,相對于%能提高運(yùn)算效率。
(2)擴(kuò)容條件
????int threshold; // 所能容納的key-value對極限
? ? final float loadFactor;? ? // 負(fù)載因子
? ? int modCount;?
? ? int size;
????首先,Node[] table的初始化長度length(默認(rèn)值是16),Load factor為負(fù)載因子(默認(rèn)值是0.75),threshold是HashMap所能容納的最大數(shù)據(jù)量的Node(鍵值對)個(gè)數(shù)。threshold = length * Load factor。也就是說,在數(shù)組定義好長度之后,負(fù)載因子越大,所能容納的鍵值對個(gè)數(shù)越多。
if (++size > threshold)
? ? ? ? ?resize();
當(dāng)大于閾值threshold 時(shí),進(jìn)行擴(kuò)容。
(3)rehash過程
? ? · 數(shù)組大小擴(kuò)容為原來的2倍。
? ? · 再散列到新數(shù)組。
(4)弊端
? ? 多線程操作可能導(dǎo)致形成循環(huán)鏈表(rehash過程)。參考https://zhuanlan.zhihu.com/p/21673805
參考:https://mp.weixin.qq.com/s?src=11×tamp=1613981827&ver=2905&signature=vByozoJ33qW-bwQ1g-YMiVEpM7Y2B8Woya-sfEgileo2AigmyECAdZFyCtdLUoDtorLq3N8w0kx-WrN9ZRD4BLY6P21gLKQxf*GS4ZSUuWh0rsKKvQ45*dK*pm0NWeKF&new=1
2.7.2 TreeMap
(1)按照比較結(jié)果的升序保存鍵值
(2)基于紅黑樹(自平衡的排序二叉樹)實(shí)現(xiàn),次序由Comparable或者Comparator決定
2.7.3 LinkedHashMap
(1)按照插入順序保存鍵值,同時(shí)保留HashMap的查詢速度
(2)使用鏈表維護(hù)內(nèi)部順序。
(3)采用基于訪問的最近最少使用(LRU)算法,沒有被訪問過的元素就會(huì)出現(xiàn)在隊(duì)列的前面。
2.7.4 HashTable
(1)線程安全,內(nèi)部的方法基本都是經(jīng)過synchronized修飾,其他使用與HashMap類似。
(2)與concurrentHashMap相比,HashTable使用全表鎖。

2.7.5 ConcurrentHashMap
? ? 與HashMap相比,線程安全,適合并發(fā)環(huán)境。
(1)JDK1.7 分段鎖
? ? ? ? 對整個(gè)通數(shù)組進(jìn)行分割分段(Segment),多線程訪問容器不同段數(shù)據(jù)時(shí),不會(huì)存在鎖競爭,提高并發(fā)訪問效率。

(2)JDK1.8 synchronized + CAS
? ? ? ? 看起來是一個(gè)優(yōu)化過且線程安全的HashMap。synchronized只鎖定當(dāng)前鏈表或紅黑樹的首節(jié)點(diǎn)。

2.8 Queue
????先進(jìn)先出(FIFO)的容器,在一端進(jìn)行插入而在另一端進(jìn)行刪除的表。
2.8.1 實(shí)現(xiàn)方式
(1)Deque接口,雙端隊(duì)列,底層實(shí)現(xiàn)可以選擇LinkedList。
(2)LinkedList
(3)PriorityQueue
? ? ? ? ? ? 優(yōu)先級(jí)隊(duì)列(堆),用Comparator對象修改排序順序,默認(rèn)為最小堆。
2.8.2 分類
(1)單隊(duì)列,存在“假溢出”問題
(2)循環(huán)隊(duì)列
2.9 比較器
2.9.1 Comparable
????來自java.lang包,使用comparaTo(Object obj)方法排序。
????Comparable是排序接口。若一個(gè)類實(shí)現(xiàn)了Comparable接口,就意味著該類支持排序。實(shí)現(xiàn)了Comparable接口的類的對象的列表或數(shù)組可以通過Collections.sort或Arrays.sort進(jìn)行自動(dòng)排序。
????此外,實(shí)現(xiàn)此接口的對象可以用作有序映射中的鍵或有序集合中的集合,無需指定比較器。
public class Person implements Comparable<Person>{
????@Override
? ? publicint compareTo(Person p)
? ? {
? ? ? ? return this.age-p.getAge();
? ? }
}
? ? 上述demo表示按照從小到大的年紀(jì)排序?qū)ο蟆?/p>
2.9.2 Comparator
? ? 來自java.util包,使用compare(Object obj1, Object obj2)方法排序。
????Comparator是比較接口,我們?nèi)绻枰刂颇硞€(gè)類的次序,而該類本身不支持排序(即沒有實(shí)現(xiàn)Comparable接口)。
? ? int compare(T o1, T o2) 是“比較o1和o2的大小”。返回“負(fù)數(shù)”,意味著“o1比o2小”;返回“零”,意味著“o1等于o2”;返回“正數(shù)”,意味著“o1大于o2”.
public class PersonCompartor implements Comparator{
? ? @Override
? ? publicint compare(Person o1, Person o2)
? ? {
? ? ? ? return o1.getAge()-o2.getAge();//從小到大排序
? ? }
}
Arrays.sort(people,new PersonCompartor());
// 定制排序的?法
Collections.sort(arrayList, new Comparator<Integer>() {
?????@Override
?????public int compare(Integer o1, Integer o2) {
?????????return o2.compareTo(o1); //從大到小排序
?????????}
? });?
注意:上面demo的compareTo方法,在String類和8種基本類型的包裝類中都含有,按字典序或自然順序排序。
2.10 工具類Collections和Arrays
2.10.1 Arrays
????在java.util中有一個(gè)Arrays類,此類包含用于操縱數(shù)組的各種方法,例如:二分查找(binarySearch)、拷貝操作(copyOf)、比較(equals)、填充(fill)、排序(sort)等,功能十分強(qiáng)大。
排序 :sort() 默認(rèn)從小到大排序
查找 :binarySearch()
比較: equals
填充 :fill(int[], int),可以用作批量初始化
轉(zhuǎn)列表: asList(int, int, int) 參數(shù)用逗號(hào)隔開
哈希:hashCode()
轉(zhuǎn)字符串 :toString()
拷貝:copyOfRange(int[], int from, int to)
2.10.2 Collections
(1)排序
void reverse(List list)//反轉(zhuǎn)
void shuffle(List list)//隨機(jī)排序
void sort(List list)//按自然排序的升序排序
void sort(List list, Comparator c)//定制排序,由Comparator控制排序邏輯
void swap(List list, int i , int j)//交換兩個(gè)索引位置的元素
void rotate(List list, int distance)//旋轉(zhuǎn)。當(dāng)distance為正數(shù)時(shí),將list后distance個(gè)元素整體移到前面。當(dāng)distance為負(fù)數(shù)時(shí),將 list的前distance個(gè)元素整體移到后面。
(2)查找替換
int binarySearch(List list, Object key)//對List進(jìn)行二分查找,返回索引,注意List必須是有序的
int max(Collection coll)//根據(jù)元素的自然順序,返回最大的元素。 類比int min(Collection coll)
int max(Collection coll, Comparator c)//根據(jù)定制排序,返回最大元素,排序規(guī)則由Comparatator類控制。類比int min(Collection coll, Comparator c)
void fill(List list, Object obj)//用指定的元素代替指定list中的所有元素。
int frequency(Collection c, Object o)//統(tǒng)計(jì)元素出現(xiàn)次數(shù)
int indexOfSubList(List list, List target)//統(tǒng)計(jì)targe在list中第一次出現(xiàn)的索引,找不到則返回-1,類比int lastIndexOfSubList(List source, list target).
boolean replaceAll(List list, Object oldVal, Object newVal), 用新元素替換舊元素