#### **前言**
本系列總結主要來自平時積累的知識點,以及傳智畢向東老師的視頻以及筆記、以及[陽哥的Java基礎教程的筆記](http://bbs.itheima.com/thread-200600-1-1.html)以及一些[大神終點的csdn博客](http://blog.csdn.net/zhangerqing/article/list/1),文章中難免有些地方不足,還請大家共同發現學習交流。
[菜鳥教程之Java教程](https://www.runoob.com/java/java-tutorial.html)
[JDK源碼在線查看-JDK6](http://hg.openjdk.java.net/jdk6/jdk6/jdk/file/8deef18bb749/src/share/classes)
[JDK源碼在線查看-JDK7U](http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/file/bcba89ce0a8c/src/share/classes/)
[JDK源碼在線查看-JDK8](http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes)
[JDK源碼在線查看-JDK10](http://hg.openjdk.java.net/jdk10/jdk10/jdk/file/777356696811/src)
[JDK 11 在線中文手冊](https://www.runoob.com/manual/jdk11api/index.html)
[JDK 1.6 在線中文手冊(舊版)](https://www.runoob.com/manual/jdk1.6/)
[W3Cschool——Java教程](https://www.w3cschool.cn/java/)
[Java教程官方網站](https://www.oracle.com/java/technologies/)
[深入理解Java虛擬機](https://www.w3cschool.cn/javavm/)
* [ ] Java發展歷史

#### **1. Java三大特性:面向對象、跨平臺(與平臺無關)、垃圾回收機制**
**Java主要特性**——大圖[請點擊這里](https://box.kancloud.cn/7551dcc8d4f6e57a8abaa013536bc284_1517x1008.png)

#### **2. 面向對象三大特征:封裝、繼承、多態**
#### 3. Android 系統中提供了一套開發工具,就不需要JAVAME
#### **4. 跨平臺性**:通過Java語言編寫的應用程序,一次編譯后,在不同的系統平臺上都可運行。
原理是只要在需要運行java應用程序的操作系統上,先安裝一個Java虛擬機(JVM Java Virtual Machine)即可。**JVM不具有跨平臺性**,不同的操作系統安裝不同版本的JVM,由JVM來負責Java程序在該系統中的運行。也稱Java有良好的可移植性。(**注意:不是所有的平臺都可運行,關鍵是該平臺是否能安裝相應的虛擬機JVM**)。

#### **5. 名詞解釋**(下面的圖示詳解了JDK、JRE、JVM、Java開發工具以及Java類庫之間的關系)
- **JDK**(Java Development Kit)Java開發工具包 : JRE+Java開發工具
- **JRE**(Java Runtime Environment)Java運行環境:JVM+類庫(Java library)
- **Java開發工具**:編譯工具(javac.exe)+打包工具(jar.exe)等等
- **API** Application Programming Interface(應用編程接口), 語言、框架以及類庫對外提供的編碼的接口。
- 使用JDK開發完成的java程序,交給JRE去運行。
**為什么JDK中包含一個JRE(使用ANSI C 實現的)呢?**
其一,開發完的程序,需要運行一下看看效果,就像exe文件需要在windows環境下運行一樣。
其二,也是最重要的,**JDK中的開發工具(如javac.exe、java.exe等)其實都是Java語言編寫的應用程序**,為了方便使用才打包成exe文件,如果沒有JRE,那么這些工具是運行不了的。
- JDK環境變量配置可以參考[這里](http://www.cnblogs.com/smyhvae/p/3788534.html),配置完成打開運行輸入cmd,打開DOS命令行,輸入java、javac、java -version檢驗是否配置成功

- java是分兩部分的:一個是編譯,一個是運行。**Java編譯器是Java實現的,Java運行環境是用ANSI C實現的**。
- javac:負責的是編譯的部分,當執行javac時,會啟動java的編譯器程序。對指定擴展名的.java文件進行編譯。 生成了jvm可以識別的字節碼文件(中立的體系結構)。也就是class文件,也就是java的運行程序。**不是只有Java語言才可以生成class文件,也就是說不只是有Java語言才可以運行在JVM上(只要能夠生成字節碼文件的語言都可以運行在JVM上)**。關于class文件的詳細介紹,可參考——[Class文件詳解](http://www.hmoore.net/alex_wsc/android_plugin/471061)
- java:負責運行的部分,會啟動jvm,加載運行時所需的類庫,并對class文件進行執行。
運行時,Java平臺中的解釋器對這些字節碼進行解釋執行,執行過程中需要的類在聯接階段被載入到運行環境中。
一個文件要被執行,必須要有一個執行的起始點,這個起始點就是main函數。如下圖所示

**備注:javap命令詳解**
通過在命令行中輸入javap -help,可以查看到javap的命令選項幫助。

**javap**:方便的反編譯工具,不能將字節碼還原為java文件,只能編譯出數據區、方法、類引用、vm指令等,不過在線上環境還是能起到快速定位問題的作用
**作用**:反編譯Java代碼,查看Java字節碼。
**用法**:`javap <options> <classes>`
**選項**:
* -version:版本信息
* -v:輸出附加信息
* -l:輸出行號和本地變量表
* -public:僅顯示公共類和成員
* -protected:顯示受保護的/公共類和成員
* -package:顯示程序包/受保護的/公共類和成員 (默認)
* -p或-private:顯示所有類和成員
* -c:對代碼進行反匯編
* -s:輸出內部類型簽名
* -sysinfo:顯示正在處理的類的系統信息 (路徑, 大小, 日期, MD5 散列)
* -constants:顯示最終常量
* -`classpath <path>`:指定查找用戶類文件的位置
* -`cp <path>`:指定查找用戶類文件的位置
* -`bootclasspath <path>`:覆蓋引導類文件的位置
>[info] 注意:
> no options(后面無任何操作):列出-package對應的成員變量、方法,不帶vm指令,例如:`javap Hello.class`
> -c 分解方法代碼,即顯示每個方法具體的字節碼,例如:`javap -c Hello.class`
#### **6. 包**
包:定義包用 package關鍵字
1:對類文件進行分管理。
2:給類文件提供多層名稱空間。
包是一種封裝形式,用于封裝類,想要被包以外的程序訪問,該類必須是public權限。
類名的全稱的是:包名.類名。
包與包之間訪問可以使用的權限有兩種:
1:public
2:protected :只能是不同包中的子類可以使用的權限。
**總結Java中的四種權限**

- jdk中常用的包
1. java.lang----包含一些Java語言的核心類,如String、Math、Integer、System和Thread,提供常用功能。
2. java.awt----包含了構成抽象窗口工具集(abstract window toolkits抽象窗口工具包)的多個類,這些類被用來構建和管理應用程序的圖形用戶界面(GUI)。
3. java.applet----包含applet運行所需的一些類。
4. java.net----包含執行與網絡相關的操作的類。網絡應用編程接口
5. java.io----包含能提供多種輸入/輸出功能的類。
6. java.util----包含一些實用工具類,如定義系統特性、使用與日期日歷相關的函數。
7. javax.swing: 提供所有的windows桌面應用程序包括的控件,比如:Frame , Dialog, Table, List 等等,就是java的圖形界面庫。
#### **7. 垃圾回收器**
- Java 的一個重要特點就是具有一個**垃圾回收器**,并**且能夠自動回收垃圾**,這也是Java相對于其他語言有優勢的地方。
- Java 類的**實例對象和數組**所需的存儲空間是**在堆上分配**的,解釋器具體承擔了為該類的實例對象分配空間的工作。解釋器在為一個實例對象分配完存儲空間后,便開始記錄對該實例對象所占用的內存區域的使用。一旦對象使用完畢,便將其回收到垃圾箱中。
- **在Java 語言中,除了new 語句外沒有任何其他方法會為一個對象申請和釋放內存**。
- Java 的自動垃圾回收功能解決了兩個最常見的應用程序錯誤:**內存泄露和無效內存的引用。**
- **Java 垃圾回收器只能管理程序中的類的實例對象,沒法去管理系統產生的資源,所以程序需要調用close 方法(是接口Closeable中的方法),去通知系統釋放其自身產生的資源**。
- **finalize 方法**
- finalize()方法是Object 類的一個方法,任何一個類都從Object 那繼承了這個方法。
- 當垃圾回收器(GC)確定不存在對該對象的更多引用時,由對象的GC調用此方法,子類重寫finalize()方法,以配置系統資源或者執行其他清除,**對于任何給定對象,JVM最多調用一次finalize()方法,如果一個對象的finalize方法被調用,就表示這個對象馬上要被從內存中清除。**
- finalize()方法是在對象被當成垃圾從內存中釋放前調用,而不是在對象變成垃圾前調用,**垃圾回收器的啟用不由程序員控制,也無規律可循,并不會一產生了垃圾,它就被喚起,甚至有可能到程序終止,它都沒有啟動的機會**。因此這并不是一個很可靠的機制,所以,我們**無法保證每個對象的finalize()方法最終都會被調用。我們只要了解一下finalize()方法的作用就行了,不要期望finalize()方法去幫我們做“需要可靠完成”的工作。**
- **System.gc的作用**
- Java 的垃圾回收器被執行的偶然性有時候也會給程序運行帶來麻煩,比如說在一個對象成為垃圾時需要馬上被釋放,或者程序在某段時間內產生大量垃圾時,釋放垃圾占據的內存空間似乎成了一件棘手的事情,如果垃圾回收器不被啟動,finalize()方法也不會被調用。為此,**Java 里提供了一個System.gc()方法,使用這個方法可以強制啟動垃圾回收器來會收垃圾**
- 手動調用這個方法,可以**強制回收垃圾**

#### **8. Java的內存(JVM內存)**
- Java程序在運行時,需要在內存中分配空間。為了提高運算效率,又對空間進行了不同區域的劃分,因為**每一片區域都有特定的處理數據方式和內存管理方式。** 下圖就是Java虛擬機運行時數據區

- java分了5片內存
- 1:寄存器,2:本地方法棧(Native Method Stack)3:方法區,4:棧(Stack)即JVM虛擬機棧,5:堆(heap)。
- 寄存器(程序計數器)——線程私有
- 每個線程都必須有一個獨立的程序計數器,這類計數器為線程私有的內存。此類內存是線程私有的內存
- 如果一個線程正在執行一個Java方法,則計數器記錄的是虛擬機字節碼指令的地址;如果執行的一個Native方法,則計數器的記錄為空,**此內存區是唯一一個在Java規范中沒有任何OutOfMemoryError情況的區域。**
- 本地方法棧——線程私有
- 本地方法棧為虛擬機使用到的Native方法服務
- 本地方法棧(Native Method Stack)與虛擬機棧(即**平常我們所說的棧**)所發揮的作用是非常相似的,它們之間的區別不過是虛擬機棧為虛擬機執行Java方法(也就是字節碼)服務,而本地方法棧則為虛擬機使用到的Native方法服務。在虛擬機規范中對本地方法棧中方法使用的語言、使用方式與數據結構并沒有強制規定,因此具體的虛擬機可以自由實現它。甚至有的虛擬機(譬如Sun HotSpot虛擬機)直接就把本地方法棧和虛擬機棧合二為一。**與虛擬機棧一樣,本地方法棧區域也會拋出StackOverflowError和OutOfMemoryError異常**。
- 方法區——線程公有
- 用于存儲已被虛擬機加載的**類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據**
- **方法區分為靜態區域和非靜態區域**
- 靜態區域存放靜態成員
- 方法區的變量也有默認值(string為null,int為0)
- 方法區又稱為數據區、共享區、共享數據區等(不同的版本翻譯也不一樣)
- **當方法區無法滿足內存分配需求時,將拋出OutOfMemoryError異常**。
- Java虛擬機規范對方法區的限制非常寬松,除了和Java堆一樣不需要連續的內存和可以選擇固定大小或者可擴展外,還可以選擇不實現垃圾收集。相對而言,垃圾收集行為在這個區域是比較少出現的,但并非數據進入了方法區就如永久代的名字一樣“永久”存在了。**這區域的內存回收目標主要是針對常量池的回收和對類型的卸載**,一般來說,這個區域的回收“成績”比較難以令人滿意,尤其是類型的卸載,條件相當苛刻,但是這部分區域的回收確實是必要的
- 運行時常量池(線程公有)
- 運行時常量池(Runtime Constant Pool)是方法區的一部分。主要用于存放在編譯過程中產生的字面量(字面量簡單理解就是**常量**)和**引用**。一般情況,常量的內存分配在編譯期間就能確定,但不一定全是,有一些可能就是運行時也可將常量放入常量池中。
- 如上面所講:運行時常量池相對于Class文件常量池的另外一個重要特征是具備動態性,Java語言并不要求常量一定只有編譯期才能產生,也就是并非預置入Class文件中常量池的內容才能進入方法區運行時常量池,運行期間也可能將新的常量放入池中,這種特性被開發人員利用得比較多的便是String類的intern()方法。
- 棧(JVM虛擬機棧)——線程私有
- 棧:**存儲的都是局部變量** ( 函數中定義的變量,函數上的參數,語句中的變量 );**只要數據運算完成所在的區域結束,該數據就會被釋放**。在函數中定義的一些基本類型的變量和對象的引用變量都是在函數的棧內存中分配
- **局部變量都是在棧內存中**,**主函數在棧里面**;
- 在方法中定義的變量(局部變量),包括基本數據類型和引用數據類型變量,都將在棧內存中分配空間,當超過變量作用范圍后自動回收。
- 函數執行要進棧,函數執行完畢就要出棧,釋放資源
- 基本類型的變量和對象的引用變量都在棧里面;這個引用變量的取值和對象在棧中的內存首地址是一一對應的。
- 線程私有,生命周期和線程相同。
- 局部變量表中存放的是各種基本數據類型,如boolean、byte、char、等8種,及引用類型(存放的是指向各個對象的內存地址),因此,它有一個特點:內存空間可以在編譯期間就確定,運行期不在改變。
- 虛擬機描述的Java方法執行的內存模型:每個方法被執行的時候會產生一個棧幀,用于存儲局部變量表、動態鏈接、操作數、方法出口等信息。**方法的執行過程就是棧幀在JVM中出棧和入棧的過程**。
- 這個內存區域會有兩種可能的Java異常:
- StackOverFlowError:線程請求的棧的深度大于虛擬機所允許的深度
- OutOfMemoryError:擴展時無法申請到足夠的內存
- 堆——線程公有
- 堆內存用來存放由new 創建的對象(包含對象的屬性和行為)和數組(**存放實體**),在堆中分配的內存,由**Java 虛擬機的自動垃圾回收器來管理**。
- 用于存儲數組和對象,也就是**實體**。啥是實體啊?就是用于封裝多個數據的。
1. 每一個實體都有內存首地址值。
2. 堆內存中的變量都有默認初始化值。因為數據類型不同,值也不一樣。
3. 垃圾回收機制。
- 關于堆的描述,深入理解Java虛擬機這樣描述
- Java堆(Java Heap)是Java虛擬機所管理的內存中最大的一塊。Java堆是被所有線程共享的一塊內存區域,在虛擬機啟動時創建。**此內存區域的唯一目的就是存放對象實例,幾乎所有的對象實例都在這里分配內存。**
- Java虛擬機規范中描述:**所有的對象實例以及數組都要在堆上分配,但是隨著JIT編譯器的發展與逃逸分析技術逐漸成熟,棧上分配、標量替換優化技術將會導致一些微妙的變化發生,所有的對象都分配在堆上也漸漸變得不是那么“絕對”了**
- Java堆是垃圾收集器管理的主要區域,因此很多時候也被稱做“GC堆”
- 如果在堆中沒有內存完成實例分配,并且堆也無法再擴展時,將會拋出OutOfMemoryError異常
總結:堆內存用來釋放由new創建的對象和數組,在堆中分配的內存,由Java虛擬機自動垃圾回收器來管理;**棧內存中定義的變量,分配的內存在程序運行到起作用域之外就會被釋放,而堆內存不會被釋放,由GC決定。**
> 在堆中產生了一個數組或對象后,我們還可以在**棧中定義一個特殊的變量**,讓棧中的這個變量的取值等于數組或對象在堆內存中的首地址,**棧中的這個變量就成了數組或對象的引用變量**,我們以后就可以在程序中使用棧中的引用變量來訪問堆中的數組或對象,引用變量就相當于是我們為數組或對象起的一個名稱(叫代號也行)。**引用變量是普通的變量,定義時在棧中分配,引用變量在程序運行到其作用域之外后被釋放**。而**數組和對象本身在堆中分配,即使程序運行到使用new 產生數組和對象的語句所在的代碼塊之外,數組和對象本身占據的內存不會被釋放,數組和對象在沒有引用變量指向它時,才會變為垃圾,不能再被使用,但仍然占據內存空間不放,在隨后一個不確定的時間被垃圾回收器收走(釋放掉)。這也是Java 比較吃內存的原因。**

在[Java之美[從菜鳥到高手演變]之JVM內存管理及垃圾回收](https://blog.csdn.net/zhangerqing/article/details/8214365)一文中介紹了JVM的內存結構

關于JVM內存的詳細介紹,可參考周志明老師的深入理解Java虛擬機:JVM高級特性與最佳實踐一書
**PS:直接內存(Direct Memory)**
- 直接內存(Direct Memory)并不是虛擬機運行時數據區的一部分,也不是Java虛擬機規范中定義的內存區域。但是這部分內存也被頻繁地使用,而且也可能導致OutOfMemoryError異常出現
- 在JDK 1.4中新加入了NIO(New Input/Output)類,引入了一種基于通道(Channel)與緩沖區(Buffer)的I/O方式,它可以使用Native函數庫直接分配堆外內存,然后通過一個存儲在Java堆中的DirectByteBuffer對象作為這塊內存的引用進行操作。這樣能在一些場景中顯著提高性能,因為避免了在Java堆和Native堆中來回復制數據。
- 本機直接內存的分配不會受到Java堆大小的限制,但是,既然是內存,肯定還是會受到本機總內存(包括RAM以及SWAP區或者分頁文件)大小以及處理器尋址空間的限制。服務器管理員在配置虛擬機參數時,會根據實際內存設置-Xmx等參數信息,但經常忽略直接內存,使得各個內存區域總和大于物理內存限制(包括物理的和操作系統級的限制),從而導致動態擴展時出現OutOfMemoryError異常。
**參考文章**:[Jvm系列5----Jvm內存模型](http://www.hmoore.net/alex_wsc/androidsystem/483875)
#### **9. JVM語言原理**

>[info]JVM規范與Java規范是相互獨立的,只要生成的編譯文件匹配JVM字節碼規范,任何語言都可以由JVM編譯運行。
Kotlin也是一種JVM語言,完全兼容java,可以與java相互調用;Kotlin語言的設計受到Java、C#、JavaScript、Scala、Groovy等語言的啟發。
#### **10. 學習 java注意的地方**
- Java語言拼寫上嚴格區分大小寫 ;
- 寫代碼,閱讀性第一,功能性第二,一定要注意寫代碼的格式!
- 一個 Java源文件里可以定義多個 Java 類, 但其中最多只能有一個類被定義成public類;
- 若源文件中包括了public類,源文件必須和該 public類同名;
- 一個源文件中包含N個Java類時,編譯后會生成N份字節碼文件,即每個類都會生成一份單獨的class文件,且字節碼文件名和其對應的類名相同;
- 將每個源文件中單獨定義的類都定義成 public的;
- 保持Java源文件的主文件名與源文件中的類名一致
- main方法的作用
- 程序的入口
- 保證程序的獨立運行
- 被JVM調用
- 一、基礎知識和概論
- 二、編程基礎
- 基本語法
- Java變量及其作用域
- Java中的字段與屬性
- Java中的運算符
- 程序的流程控制
- 方法和數組
- 編程規約之代碼格式
- 排序算法
- 三、面向對象
- 面向對象上
- 面向對象下
- 面向對象特征之類的繼承
- 抽象類和接口
- 面向對象特征之多態
- 內部類
- 編碼規約之OOP規約
- 四、異常處理
- 異常的體系
- 異常的處理格式
- 異常的分類
- 自定義異常
- 使用細節
- 阿里Java開發手冊之“異常”
- 五、多線程
- 線程和進程
- 創建線程方式
- 控制線程
- 多線程安全問題
- 線程間通信
- 線程池
- Java并發編程:線程池的使用(轉)
- 傳統定時器技術
- Java并發編程:Timer和TimerTask
- 阿里Java之并發處理
- Java并發編程:volatile關鍵字解析
- 關于線程的面試題
- JAVA多線程和并發基礎面試問答
- Java線程面試題 Top 50
- 六、集合框架
- 集合類 & 容器
- Collection 接口和Iterator 接口
- List接口
- Set接口
- Map接口
- 使用集合的技巧
- Collections類
- Arrays工具類
- 阿里Java之集合
- 七、Jdk1.5新特性
- 增強for循環
- 可變參數
- 枚舉
- 自動拆裝箱
- 泛型
- 靜態導入
- 八、IO流
- IO流
- 字符流
- 字節流
- File類
- 遞歸
- PrintStream
- PrintWriter
- SequenceInputStream
- RandomAccessFile
- 管道流
- 對象的序列化
- 編碼表
- 示例
- 深入理解 Java中的 流(Stream)機制
- 九、常用類API使用說明
- System
- Runtime
- Math
- Date
- Calendar
- StringBuffer 與 StringBuilder
- Random
- UUID
- String
- Integer對象
- 深入理解Java中的String
- 十、網絡編程
- 網絡基礎概念
- 網絡參考模型
- 網絡通訊要素
- 域名解析
- UDP協議-發送端&接收端
- TCP協議-客戶端&服務端
- 了解客戶端和服務器端原理
- Android_IPC機制之使用Socket
- Http和Socket區別
- Android網絡編程之TCP、IP、UDP、HTTP、Socket之間的關系
- Android中用Socket編程實例
- 十一、高新技術
- 反射技術
- 注解
- 類加載
- 一
- 二
- Class類文件的結構
- 代理
- 黑馬代理講解
- 網絡文章總結
- java動態代理學習筆記
- java反射與代理
- JavaBean內省
- 正則表達式
- Java回調
- 反射和自定義注解的使用
- Java注解反射原理
- 設計模式
- 單例設計模式
- 抽象類的體現-模板模式
- 簡單工廠模式
- 適配器模式
- 代理模式
- 面試復習
- Java8新特性
- 深入理解Java虛擬機
- JDK9新特性
- (轉)JDK各個版本的新特性jdk1.5-jdk8