本文內(nèi)容為學習筆記,用于個人知識點總結(jié)、復習。
原教學視頻出自:中國大學MOOC網(wǎng) |《Java核心技術(高階)》 ——陳良育
第一章 Java語法糖
第一節(jié) 語法糖和環(huán)境設置
第二節(jié) 語法糖(1)for-each和枚舉
-
for vs for-each
語法糖(for-each).png
1.for-each從JDK5.0引入
2.for-each語法更簡潔
3.for-each避免越界錯誤
4.for可以刪除元素,for-each不可以刪除/替換元素
5.for-each便利的時候,不知道當前元素的具體位置索引
6.for-each只能正向遍歷,不能反向遍歷
7.for-each不能同時遍歷2個集合
8.for和for-each性能接近 -
枚舉
語法糖(枚舉1).png
語法糖(枚舉2).png Java的enum類型
1.所有的enum類型都是Enum的子類,也繼承了相應方法
2.ordinal()返回枚舉值所在的索引位置,從0開始
3.compareTo()比較兩個枚舉值的索引位置大小
4.同String()返回枚舉值的字符串表示
5.valueOf()將字符串初始化為枚舉對象
6.values()返回所有的枚舉值
第三節(jié) 語法糖(2)不定項參數(shù)和靜態(tài)導入
-
不定項參數(shù)
語法糖(不定項參數(shù)).png
1.一個方法只能有一個不定項參數(shù),且必須位于參數(shù)列表的最后
2.重載的優(yōu)先級規(guī)則:
- 固定參數(shù)的方法優(yōu)先級大于可變參數(shù)
- 調(diào)用語句,同時與兩個帶可變參數(shù)的方法匹配,則報錯 -
靜態(tài)導入
語法糖(靜態(tài)導入1).png
第四節(jié) 語法糖(3)自動拆箱和裝箱、多異常并列、數(shù)值類型賦值優(yōu)化
-
自動裝箱與拆箱
語法糖(自動裝箱與拆箱1).png
語法糖(自動裝箱與拆箱2).png1.裝箱和拆箱是編譯器的工作,在class中已經(jīng)添加轉(zhuǎn)化。虛擬機沒有自動裝箱和拆箱的語句
2.==:基本類型是內(nèi)容相同,對象是地址相同
3.基本類型沒有空值,對象有null,可能觸發(fā)NullPointerException
4.當一個基礎數(shù)據(jù)類型與封裝類進行運算時,會自動拆箱
5.謹慎使用多個非同類的數(shù)值類對象進行運算 -
多異常并列
語法糖(多異常并列1).png
語法糖(多異常并列2).png 數(shù)值類型賦值優(yōu)化
1.整數(shù)類型用二進制數(shù)賦值
2.數(shù)字中的下劃線
第五節(jié) 語法糖(4)接口方法
第六節(jié) 語法糖(5)try-with-resource和Resource Bundle文件加載
-
try-with-resource
語法糖(try-with-resource1).png -
ResourceBundle文件加載
1.Java8以前,需要用native2ascii工具對文件轉(zhuǎn)義
2.JDK9后,ResourceBundle默認以UTF-8方式加載Properties文件,刪除native2ascii工具u,Properties文件可以直接以UTF-8保存
語法糖(try-with-resource2).png
第七節(jié) 語法糖(6)var類型和switch
-
var
語法糖(var1).png
1.可以用在局部變量上,非類成員變量
2.可以用在for/for-each循環(huán)中,可用于三元操作符,對繼承有效
3.聲明時必須初始化
4.不能用在形參和返回類型
5.大面積運用會使代碼整體閱讀性變差
6.var指在編譯時起作用,沒有在字節(jié)碼中引入新的內(nèi)容,也沒有專門的JVM指令處理var -
switch
語法糖(switch1).png
第二章 Java泛型
第一節(jié) 泛型入門
- 泛型的本質(zhì):參數(shù)化類型<E>,避免類型轉(zhuǎn)換,代碼可復用
泛型分類.png
泛型(ArrayList源碼).png
第三章 Java反射
第一節(jié) 反射入門
- 反射:reflection
1.程序可以訪問、檢測和修改它本身狀態(tài)或行為的能力,即自描述和自控制
2.可以在運行時加載、探知和使用編譯期間完全未知的類
3.給Java插上動態(tài)語言特性的翅膀,彌補強類型語言的不足
4.java.lang.reflect包 -
反射的應用
1.在運行中分析類的能力
2.在運行中查看和操作對象
- 基于反射自由創(chuàng)建對象
- 反射構建出無法直接訪問的類
- set或者get到無法訪問的成員變量
- 調(diào)用不可訪問的方法
3.實現(xiàn)通用的數(shù)組操作代碼
4.類似函數(shù)指針的功能
創(chuàng)建對象方法(1).png
第四章 Java代理
第一節(jié) 代理模式和靜態(tài)代理
-
代理模式
代理示意圖.png 為目標對象提供(包裝)了一個代理,這個代理可以控制對目標對象的訪問
1.外界不用直接訪問目標對象,而是訪問代理對象,由代理對象再調(diào)用目標對象
2.代理對象中可以添加監(jiān)控和審查處理-
靜態(tài)代理
1.代理對象持有目標對象的句柄
2.所有調(diào)用目標對象的方法,都吊用代理對象的方法
3.對每個方法,需要靜態(tài)編碼
靜態(tài)代理示意圖.png
靜態(tài)代理代理類代碼.png
第二節(jié) 動態(tài)代理
-
動態(tài)代理
動態(tài)代理示意圖.png
動態(tài)代理流程圖.png
動態(tài)代理代理處理器類代碼.png
動態(tài)代理主類代碼.png
動態(tài)代理(實現(xiàn)多接口)主類代碼.png
第五章 Java注解
第一節(jié) 注解入門
-
注解示例
壓制警告注解示例.png
重寫方法標記注解示例.png - 注解
1.JDK1.5引入
2.位于源碼中(代碼/注釋/注解),使用其他工具進行處理的標簽
3.注解用來修飾程序的元素,但不會對被修飾的對象有直接的影響
4.只有通過某種配套工具才會對注解信息進行訪問和處理 -
注解用途
1.提供信息給編譯器/IDE工具
2.可用于其他工具來產(chǎn)生額外的代碼/配置文件等
3.有一些注解可在程序運行時訪問,增加程序的動態(tài)性
注解(普通)示例.png
注解(元)示例.png
第六章 嵌套類
第一節(jié) 嵌套類入門
-
嵌套類:嵌套,一個類定義在別的類內(nèi)部
1.靜態(tài)嵌套類:即類前面有static修飾符
2.非靜態(tài)嵌套類(內(nèi)部類)
- 普通內(nèi)部類(成員內(nèi)部類)
- 局部內(nèi)部類
- 匿名內(nèi)部類
靜態(tài)嵌套類.png
普通內(nèi)部類.png
局部內(nèi)部類.png
匿名內(nèi)部類.png - 嵌套類優(yōu)缺點
1.不同的訪問權限要求,更細粒度的訪問控制
2.簡潔,避免過多的類定義
3.語言設計過于復雜,較難學習和使用
第七章 Lambda表達式
第一節(jié) Lambda表達式入門
-
示例
字符串數(shù)組排序(一般方法).png
字符串數(shù)組排序(Lambda方法).png - Lambda表達式
1.類似于匿名方法
2.參數(shù),箭頭,表達式語句
3.可以忽略寫參數(shù)類型
4.堅決不聲明返回值類型
5.沒有public/private/static/final等修飾符
6.單句表達式將直接返回值,不用大括號
7.帶return語句,算多句,必須用大括號
第八章 Java Stream流
第一節(jié) 流的概述
-
示例
字符串數(shù)組篩選統(tǒng)計(一般方法).png
字符串數(shù)組篩選統(tǒng)計(流方法).png -
Stream語法
Stream語法示例.png
第九章 Java模塊化
第一節(jié) Java模塊化概述
- 現(xiàn)狀:以Jar為中心
1.jar文件無法控制別人訪問其內(nèi)部的public的類
2.無法控制不同jar包中,相同的類名(包名+類名)
3.Java運行時,無法判定classpath路徑上的jar中有多少個不同版本文件。Java加載第一個符合名字的類
4.Java運行時,無法預判classpath路徑上是否缺失了一些關鍵類 - 模塊化三原則
1.強封裝性:能對其他模塊隱藏部分代碼
2.定義接口良好:模塊必須向其他模塊公開定義良好且穩(wěn)定的接口
3.顯示依賴:明確一個模塊需要哪些模塊的支持才能完成工作 - 模塊化系統(tǒng):Jigsaw拼圖
1.以模塊為中心
2.對JDK本身進行模塊化
3.提供一個應用程序可以使用的模塊系統(tǒng)
4.優(yōu)點
- 可靠的配置
- 強封裝性
- 可擴展開發(fā)
- 安全性
- 性能優(yōu)化
第十章 Java字節(jié)碼
第一節(jié) 字節(jié)碼概述
-
Java開發(fā)過程
Java開發(fā)過程.png -
.class文件:字節(jié)碼(bytecode)文件
1.class文件是Java“一次編譯,到處運行”的基礎
2.class文件具備平臺無關性,有JVM執(zhí)行
3.每個class文件包含一個類或接口或模塊的定義
4.class文件是一個二進制文件,有JVM定義class文件的規(guī)范
5.任何滿足這種規(guī)范的class文件都會被JVM加載運行
6.class文件可以由其他語言編譯生成,甚至不用程序語言直接生成
7.JDK版本不同,所編譯出.class文件略有不同
Java字節(jié)碼跨平臺示意圖.png
第十一章 Java類加載器
第一節(jié) Java類加載機制
- 類加載過程
1.程序是依靠多個Java類共同協(xié)作完成的
2.JVM一句classpath執(zhí)行的類庫的順序來查找類
3.潛在的問題
- 如何找到正確的類,如classpath路徑的前后
- 如何避免惡意的類,如一個假的String類
- 加載的順序,如先加載父類,還是子類 - 類加載器ClassLoader
1.負責查找、加載、校驗字節(jié)碼的應用程序
2.java.lang.ClassLoader
- load(String className)根據(jù)名字加載一個類,返回類的實例
- defineClass(String name,bute【】 b,int off,int len)將一個字節(jié)流定義一個類
- findClass(String name)查找一個類
- findLoadedClass(String name)在已加載的類中,查找一個類
- 成員變量ClassLoader parent; -
JVM四級類加載器
1.啟動類加載器(Bootstrap),系統(tǒng)類rt.jar
2.擴展類加載器(Extension),jre/lib/ext
3.應用類加載器(App),classpath
4.用戶自定義加載器(Plugin),程序自定義
JVM四級類加載器示意圖.png -
類加載器雙親委托
1.首先判斷是否已經(jīng)加載
2.若無,找父加載器加載
3.若再無,由當前加載器加載
類加載器源碼.png
類加載機制示例代碼.png
第二節(jié) Java類雙親委托加載擴展
Java嚴格執(zhí)行雙親委托機制
1.類會由最頂層的加載器來加載,如沒有,才有下級加載器加載
2.委托是單向的,確保上層核心的類的正確性
3.但是上級類加載器所加載的類,無法訪問下級類加載器所加載的類,可能會導致問題。例如:核心類庫(由BootStrapClassLoader加載)中有很多接口類需通過自定義類(由PluginClassLoader加載)實現(xiàn),如JDBC和XML Parser等-
雙親委托的補充
1.執(zhí)行Java,添加虛擬機參數(shù)-Xbootclasspath/a:path,將類路徑配置為Bootstrap等級
java-X幫助.png 示例:A工程某類實現(xiàn)a方法,B工程同名類實現(xiàn)b方法。B中主類獲取類的類加載器名為AppClassLoader并執(zhí)行b方法,執(zhí)行上圖操作將A中該類路徑配置為BootStrap等級,此時B中主類獲取類的類加載器名為BootstrapClassLoader并執(zhí)行a方法
2.使用ServiceLoader.load方法,來加載底層加載器所加載的類-
示例:java.sql.DriverManager是Bootstrap加載器加載的,需要訪問到com.mysql.jdbc.Driver類
DriverManager源碼.png
MysqlJar包Driver接口文件.png
調(diào)用服務示意圖.png
第三節(jié) 自定義類加載路徑
- 自定義加載路徑
1.彌補類搜索路徑靜態(tài)的不足
2.URLClassLoader,從多個URL(jar或者目錄)中加載類 -
URLClassLoader
1.繼承于ClassLoader
2.程序運行時增加新的類加載路徑
3.可以從多個來源中加載類(目錄/jar包/網(wǎng)絡)
4.addURL添加路徑
5.close方法關閉
URLClassLoader構造方法.png
自定義類加載路徑代碼.png
=====示例代碼待補充(自定義類加載路徑)=====
第四節(jié) 自定義類加載器
- 自定義類加載器
1.繼承ClassLoader類
2.重寫findClass(String className)方法
3.使用時,默認先調(diào)用loadClass(className)來查看是否已經(jīng)加載過,然后委托雙親加載,如果都沒有,再通過findClass加載返回
- 在findClass中,首先讀取字節(jié)碼文件
- 然后,調(diào)用defineClass(className,bytes,off,len)將類注冊到虛擬機中
- 可以重寫loadClass方法突破雙親加載
=====示例代碼待補充(自定義類加載類)=====
第五節(jié) Java類加載器總結(jié)與展望
-
JVM類裝載過程
JVM類裝載過程.png
第十二章 JVM內(nèi)存管理
第一節(jié) JVM概述
-
虛擬機
1.邏輯上,一臺虛擬的計算機
2.實際上,一個軟件,能夠執(zhí)行一系列虛擬的計算指令
3.系統(tǒng)虛擬機:對物理計算機的仿真,如VMWare
4.軟件虛擬機:專門為單個計算程序而設計,如JVM
JVM概覽.png
第二節(jié) JVM內(nèi)存分類
- Java自動內(nèi)存管理:程序員申請使用,系統(tǒng)檢查無用對象并回收內(nèi)存,內(nèi)存使用相對高效,但也會出現(xiàn)異常
- JVM內(nèi)存
1.線程私有內(nèi)存
- 程序計數(shù)器
- Java虛擬機棧
- 本地方法棧
2.多線程共享內(nèi)存
- 堆
- 方法區(qū)(運行時常量池) - 程序計數(shù)器
1.一塊小內(nèi)存,每個線程都有
2.存儲當前方法(線程正在執(zhí)行的方法)
3.當前方法為本地方法(native)(如c語言方法)時,pc值未定義(undefined)
4.當前方法為非本地方法(如java方法)時,pc包含了當前正在執(zhí)行指令的地址
5.當前唯一一塊不會引發(fā)OutOfMemoryError異常 - Java虛擬機棧(Java JVM stack)
1.每個方法從調(diào)用到完成對應一個棧幀在棧中入棧、出棧的過程
- 棧幀存儲局部變量表、操作數(shù)棧等
- 局部變量表存放方法中存在“棧”里面的東西
2.引發(fā)的異常
- 棧的深度超過虛擬機規(guī)定深度,StackOverflowError異常
- 無法擴展內(nèi)存,OutOfMemoryError異常 - 本地方法棧(Native Method Stacks)
1.存儲native方法的執(zhí)行信息(調(diào)用c函數(shù)時)
2.異常:
- 棧的深度超過虛擬機規(guī)定深度,StackOverflowError異常
- 無法擴展內(nèi)存,OutOfMemoryError異常 - 堆(Heap)
1.虛擬機啟動時創(chuàng)建,所有線程共享,占地最大
2.對象實例和數(shù)組都是在堆上分配內(nèi)存(int等小數(shù)據(jù)放在虛擬機棧)
3.垃圾回收的主要區(qū)域
4.設置大小:-Xms初始堆值,-Xmx最大堆值
5.異常:無法滿足內(nèi)存分配要求,OutOfMemoryError異常 - 方法區(qū)
1.存儲JVM已經(jīng)加載類的結(jié)構,所有線程共享:運行時常量池、類信息、常量、靜態(tài)變量等
2.JVM啟動時創(chuàng)建,邏輯上屬于堆的一部分
3.很少做垃圾回收
4.異常:無法們組內(nèi)存分配要求,OutOfMemoryError異常 -
運行時常量池
1.Class文件常量池的運行時表示
2.方法區(qū)的一部分
3.動態(tài)性:Java語言并不要求常量一定只有在編譯期產(chǎn)生,比如String.intern方法
4.異常:無法滿足內(nèi)存分配要求,OutOfMemoryError異常
JVM內(nèi)存.png
第三節(jié) JVM內(nèi)存參數(shù)
-
JVM默認運行參數(shù)
1.支持JVM運行的重要配置,根據(jù)操作系統(tǒng)/物理硬件不同而不同
2.使用-XX:+PrintFlagsFinal顯示VM的參數(shù)
JVM運行參數(shù).png
JVM程序啟動參數(shù).png -
堆OOM示例
堆OOM示例.png -
JVM棧StackOverflow示例
JVM棧StackOverflow示例.png
JVM棧StackOverflow示例2.png -
方法區(qū)
方法區(qū)OOM示例.png
第四節(jié) Java對象引用
GC
1.什么內(nèi)存需要收集(判斷無用對象)
2.什么時候回收(何時啟動,不影響程序正常運行)
3.如何回收(回收過程,要求速度快/時間短/影響小)Java對象的生命周期
1.對象通過構造函數(shù)創(chuàng)建,但是沒有析構函數(shù)回收內(nèi)存
2.對象存活在離他最近的一對大括號中內(nèi)存回收API
1.Object的finalize方法,垃圾回收器在回收對象時調(diào)用,有且僅被調(diào)用一次
2.System的gc方法,運行垃圾收集器Java隊形引用
1.基于對象引用判定無用對象:零引用,互引用
2.對象引用鏈GC Roots:可達性分析起點
1.虛擬機棧中引用的對象
2.方法區(qū)中類靜態(tài)屬性引用的對象
3.方法區(qū)中常量引用的對象
4.本地方法棧中引用的對象Java引用方式
1.強引用,只要強引用還存在,對象就不會被回收,哪怕發(fā)生OOM異常,如:Object obj= new Object();Object obj2=obj;
2.軟引用,描述有用但并非必須的對象,OOM時回收
3.弱引用,只能存活到下一次垃圾收集之前
4.虛引用,目的是能在某個對象被收集器回收時收到一個系統(tǒng)通知,用于對象回收跟蹤
第五節(jié) 垃圾收集算法
- 引用計數(shù)法
1.每個對象有一個引用計數(shù)器,有引用計數(shù)器加一,引用失效計數(shù)器減一,計數(shù)器為0,將被回收
2.優(yōu)點:簡單,效率高;缺點:無法識別對象之間的相互循環(huán)引用 - 標記-清除
1.標記:標記出所有需要回收的對象(引用計數(shù)法);回收:統(tǒng)一回收所有被標記的對象
2.優(yōu)點:簡單;缺點:效率不高,內(nèi)存碎片 - 復制算法
1.將可用內(nèi)存分成兩份,一份用完后把其中存活對象復制到另一份,使用過的內(nèi)存全部清除
2.優(yōu)點:簡單、高效;缺點:可用內(nèi)存減少,對象存活率高是復制操作較多 - 標記-整理
1.標記:標記待回收對象,讓所有存活對象向一邊移動,然后清理掉段邊界以外內(nèi)存
2.優(yōu)點:避免碎片產(chǎn)生,無需兩塊相同內(nèi)存;缺點:計算代價大,標記清除+碎片整理,更新引用地址 -
分代收集
1.Java對象生命周期不同有長有短
2.根據(jù)對象存活周期,將內(nèi)存分成新生代和老年代
3.新生代:復制算法
- 主要存放短暫生命周期的對象
- 新創(chuàng)建的對象都先放入新生代,大部分新建對象在第一次gc時被回收
4.老年代:標記清除或標記整理
- 一個對象經(jīng)過幾次gc仍存活則放入老年代
- 這些對象可以活很長時間或伴隨程序一生,需要常駐內(nèi)存,可以減少回收次數(shù)
堆內(nèi)存示意圖.png
新生代gc算法1.png
第六節(jié) JVM對內(nèi)存參數(shù)和GC跟蹤
第七節(jié) JVM內(nèi)存管理總結(jié)和展望
第十三章 Java運行管理
第一節(jié) Java運行管理概述
-
Java開發(fā)和運行過程
Java開發(fā)過程.png
1.類加載器加載class文件
2.存儲在JVM Memory中
3.然后JVM執(zhí)行機獲取memory的東西,獲取到字節(jié)碼指令,翻譯成本地方法,然后執(zhí)行
Java運行管理.png - OS管理
1.進程級別的管理(黑盒)
2.CPU/內(nèi)存/IO等具體性能監(jiān)控 - JVM管理
1.線程/程序級別的管理(白盒)
2.查看虛擬機運行時各項信息
3.跟蹤程序的執(zhí)行過程,查看程序運行時信息
4.限制程序?qū)Y源使用
5.將內(nèi)存導出為文件進行具體分析