1. 程式人生 > >Java基礎知識回顧之七 ----- 總結篇

Java基礎知識回顧之七 ----- 總結篇

停止 pub mina 特定 文本 定義 們的 value 鍵值

前言

在之前Java基礎知識回顧中,我們回顧了基礎數據類型、修飾符和String、三大特性、集合、多線程和IO。本篇文章則對之前學過的知識進行總結。除了簡單的復習之外,還會增加一些相應的理解。

基礎數據類型

基本數據類型主要有:
byte、short、int、long、float、double、char、boolean
它們可以分為三類:

  1. 數值類型:byte、short、int、long、float、double
  2. 字符類型:char
  3. 布爾型:boolean

其中byte是8位,short是16位, int是32位以及 long是64的整數;而float 32位,double 64 位的浮點數。

數值類型的級別從低到高分別為:
byte,char,short(這三個平級)——>int——>float——>long——>double
其中由低級別轉到高級別,是屬於自動類型轉換,這點是由系統自動轉換的。在進行計算的時候,如果級別小於int,最終的數據類型會自動轉換為int,如果高於int,最終數據結果會取其中最高的一個。
又高級別轉到低級別是強制類型轉換強制類型轉換需要註意取值範圍和數據的精確度

char是字符類型,可以儲存任何字符。
boolean是布爾類型,只有false或true。

基礎數據類型更詳細的說明:http://www.panchengming.com/2018/03/18/pancm76/

一般我們在用基礎數據類型的時候,也會用到包裝類型。
這裏順便說下包裝類型,也來彌補之前的文章講述不足。

什麽是包裝類型?包裝類型和基礎數據類型的關系。
包裝類就是基本類型數據轉換為對象的一種類型。

每個基本類型在java.lang包中都有一個相應的包裝類。
基礎數據類型:
boolean, char, byte,short,int, long, float,double
分別對應的包裝數據類型:
Boolean,Character,Byte,Short,Integer,Long,Float,Double

包裝類型有什麽用

  1. 利於實現基本類型之間的轉換;
    因為我們了解到基本數據類型之間的相互轉換分為自動類型轉換

    強制類型轉換自動類型轉換還好,但是強制類型轉換容易出現問題。所以出現了包裝類型,它可以很方便的幫助轉換。
    例如: String類型的轉int類型可以通過 Integer.parseInt()轉換成int,或使用Integer.valueOf()轉換成Integer類型。

  2. 便於函數傳值;
    為什麽說方面函數傳值呢?假如一個方法的入參是Object 類型, 但是你的入參是個int類型,是無法直接調用這個方法的,所以這時便可以將int類型的數據進行包裝成Integer類型,在進行調用便可以了。其實除了這個示例,比較常見的是我們的pojo類型,一般會使用包裝類型,這樣的話在便可以使用null來進行判斷。不止這些,在集合的List、Map和Set等等泛型中的類型是,用的是包裝類型,例如: Map<String,Integer> map=new HashMap<String,Integer>();

註意:在使用包裝數據類型進行值比較的時候,用equals進行比較,不要用==。例如:

    Integer a=127;
    Integer b=127;
    Integer c=128;
    Integer d=128;
    System.out.println(a == b);
    System.out.println(a.equals(b));
    System.out.println(c == d);
    System.out.println(c.equals(d));

輸出結果:

true
true
false
true

修飾符

Java修飾符主要分為兩類:

  • 訪問修飾符
  • 非訪問修飾符

其中訪問修飾符主要包括 private、default、protected、public。
非訪問修飾符主要包括 static、final、abstract、synchronized。

訪問修飾符

訪問修飾符的訪問權限:
| 修飾符 | 當前類 | 同一包內 | 子類 | 其它包 |
| :-----: | :-----:| :------: | :----:| :---: |
| public | Y | Y | Y | Y |
| protected | Y | Y | Y | N |
| default | Y | Y | N | N |
| private | Y | N | N | N |

非訪問修飾符

static: 用來修飾類變量和類方法。
修飾變量

static在修飾類變量的時候,無論該類被實例化了多少次,它的靜態變量只有一份拷貝。靜態變量也被稱為類變量。局部變量是不能被聲明為static變量的。

修飾方法

static在修飾類方法的時候,靜態方法是不能使用類的非靜態變量。靜態方法可以直接通過類名調用,因此靜態方法中是不能用thissuper關鍵字的。

final :用來修飾類、方法和變量。

final 修飾的類不能夠被繼承,修飾的方法不能被繼承類重新定義,修飾的變量為常量,是不可修改的。

abstract :用來創建抽象類和抽象方法。
修飾類

會使這個類成為一個抽象類,這個類將不能生成對象實例,但可以做為對象變量聲明的類型(見後面實例),也就是編譯時類型。抽象類就相當於一類的半成品,需要子類繼承並覆蓋其中的抽象方法。

修飾方法

會使這個方法變成抽象方法,也就是只有聲明而沒有實現,需要子類繼承實現。

synchronized: 修飾的方法同一時間只能被一個線程訪問。

transient:被 transient 修飾的實例變量時,java 虛擬機(JVM)跳過該特定的變量。

native: 被native修飾的方法實際是由另一種語言進行實現的本地方法

修飾符更詳細的說明:http://www.panchengming.com/2018/03/24/pancm77/

三大特性

封裝

封裝可以被認為是一個保護屏障,防止該類的代碼和數據被外部類定義的代碼隨機訪問。要訪問該類的代碼和數據,必須通過嚴格的接口控制。

使用封裝的好處

  1. 良好的封裝能夠減少耦合。

  2. 類內部的結構可以自由修改。

  3. 可以對成員變量進行更精確的控制。

  4. 隱藏信息,實現細節。

繼承

繼承是java面向對象編程技術的一塊基石,因為它允許創建分等級層次的類。
繼承就是子類繼承父類的特征和行為,使得子類對象(實例)具有父類的實例域和方法,或子類從父類繼承方法,使得子類具有父類相同的行為。

優缺點

雖然繼承大大提升了代碼的復用性,但是也提高了類之間的耦合性!

多態

多態是指事物在運行過程中存在不同的狀態。

多態的優點

  1. 可替換性(substitutability)。多態對已存在代碼具有可替換性。例如,多態對圓Circle類工作,對其他任何圓形幾何體,如圓環,也同樣工作。
  2. 可擴充性(extensibility)。多態對代碼具有可擴充性。增加新的子類不影響已存在類的多態性、繼承性,以及其他特性的運行和操作。實際上新加子類更容易獲得多態功能。例如,在實現了圓錐、半圓錐以及半球體的多態基礎上,很容易增添球體類的多態性。
  3. 接口性(interface-ability)。多態是超類通過方法簽名,向子類提供了一個共同接口,由子類來完善或者覆蓋它而實現的。
  4. 靈活性(flexibility)。它在應用中體現了靈活多樣的操作,提高了使用效率。
  5. 簡化性(simplicity)。多態簡化對應用軟件的代碼編寫和修改過程,尤其在處理大量對象的運算和操作時,這個特點尤為突出和重要。

三大特性更詳細的說明:http://www.panchengming.com/2018/03/24/pancm78/

集合

List

List 接口是繼承於 Collection接口並定義 一個允許重復項的有序集合。該接口不但能夠對列表的一部分進行處理,還添加了面向位置的操作。

List的常用類

  • ArrayList:內部是通過數組實現的,它允許對元素進行快隨機訪問。當從ArrayList的中間位置插入或者刪除元素時,需要對數組進行復制、移動、代價比較高。因此,它適合隨機查找和遍歷,不適合插入和刪除。
  • LinkedList: 則是鏈表結構存儲數據的,很適合數據的動態插入和刪除,隨機訪問和遍歷速度比較慢。另外,他還提供了List接口中沒有定義的方法,專門用於操作表頭和表尾元素,可以當作堆棧、隊列和雙向隊列使用。
  • Vector: 通過數組實現的,不同的是它支持線程的同步。訪問速度ArrayList慢。

推薦單線程使用ArrayList進行查詢和遍歷,LinkedList進行插入和刪除。
多線程使用Collections.synchronizedList方法對List上鎖,效率比Vector高。

Map

Map 接口並不是 Collection 接口的繼承。Map提供key到value的映射。一個Map中不能包含相同的key,每個key只能映射一個value。Map接口提供3種集合的視圖,Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射。

Map常用類

  • HashMap: HashMap的鍵是根據HashCode來獲取,所以根據鍵可以很快的獲取相應的值。不過它的鍵對象是不可以重復的,它允許鍵為Null,但是最多只能有一條記錄,不過卻是可以允許多條記錄的值為Null。因為HashMap是非線程安全的,所以它的效率很高。
  • TreeMap:可以將保存的記錄根據鍵進行排序,默認是按鍵值的升序排序(自然順序)。也可以指定排序的比較器,當用Iterator遍歷TreeMap時,得到的記錄是排過序的。它也是不允許key值為空,並且不是線程安全的。
  • LinkedHashMap:LinkedHashMap基本和HashMap一致。不過區別在與LinkedHashMap是維護一個雙鏈表,可以將裏面的數據按寫入 的順序讀出。可以認為LinkedHashMap是HashMap+LinkedList。即它既使用HashMap操作數據結構,又使用LinkedList維護插入元素的先後順序。它也不是線程安全的。
  • Hashtable:Hashtable與HashMap類似,可以說是HashMap的線程安全版。不過它是不允許記錄的鍵或者值為null。因為它支持線程的同步,是線程安全的,所以也導致了Hashtale在效率較低。
  • ConcurrentHashMap: ConcurrentHashMap在Java 1.5作為Hashtable的替代選擇新引入的。使用鎖分段技術技術來保證線程安全的,可以看作是Hashtable的升級版。

推薦單線程隨機查詢用HashMap,自然順序或自定義順序用TreeMap,插入和刪除用LinkedHashMap。
多線程推薦使用ConcurrentHashMap。

Set

Set是一種不包含重復的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。因為Set是一個抽象的接口,所以是不能直接實例化一個set對象。Set s = new Set() 這種寫法是錯誤的。

推薦單線程隨機查詢用HashSet,自然順序或自定義順序用TreeSet,插入和刪除用LinkedHashSet。

集合更詳細的說明:http://www.panchengming.com/2018/04/19/pancm80/

多線程

多線程是指在同一程序中有多個順序流在執行。 簡單的說就是在一個程序中有多個任務運行。

線程的狀態

創建(new)狀態: 準備好了一個多線程的對象
就緒(runnable)狀態: 調用了start()方法, 等待CPU進行調度
運行(running)狀態: 執行run()方法
阻塞(blocked)狀態: 暫時停止執行, 可能將資源交給其它線程使用
終止(dead)狀態: 線程銷毀

線程的創建

  • 通過實現 Runnable 接口;
  • 通過繼承 Thread 類本身;
  • 通過實現 Callable接口,然後與Future 和創建線程。

註:線程啟動的方法是start而不是run。
推薦創建單線程的時候使用繼承 Thread 類方式創建,多線線程的時候使用Runnable、Callable 接口的方式來創建創建線程。

線程的常用方法

  1. sleep:在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),不會釋放對象鎖。
  2. join:指等待t線程終止。
  3. yield:暫停當前正在執行的線程對象,並執行其他線程。
  4. setPriority:設置一個線程的優先級。
  5. interrupt:一個線程是否為守護線程。
  6. wait:強迫一個線程等待。它是Object的方法,也常常和sleep作為比較。需要註意的是wait會釋放對象鎖,讓其它的線程可以訪問;使用wait必須要進行異常捕獲,並且要對當前所調用,即必須采用synchronized中的對象。
  7. isAlive: 判斷一個線程是否存活。
  8. activeCount: 程序中活躍的線程數。
  9. enumerate: 枚舉程序中的線程。
  10. currentThread: 得到當前線程。
  11. setDaemon: 設置一個線程為守護線程。(用戶線程和守護線程的區別在於,是否等待主線程依賴於主線程結束而結束)。
  12. setName: 為線程設置一個名稱。
  13. notify(): 通知一個線程繼續運行。它也是Object的一個方法,經常和wait方法一起使用。

多線程更詳細的說明:http://www.panchengming.com/2018/05/28/pancm84/

多線程中經常會使用這幾個關鍵字synchronizedlockvolatile
synchronized: synchronized是JVM級別的,也就是在運行期由JVM解釋的。它是阻塞鎖(也就是在同一時間只會有一個線程持有);也是非公平鎖(也就是不遵循先來後到的原則,當一個線程A持有鎖,而線程B、C處於阻塞狀態時,若線程A釋放鎖,JVM將從線程B、C隨機選擇一個線程持有鎖並使其獲得執行權)。可以保證原子性、可見性以及有序性。

lock: lock是通過編碼實現的。它是非阻塞鎖;也是公平鎖。可以保證原子性、可見性以及有序性。相比synchronized,更加靈活和強大。

volatile:輕量級的鎖。主要用戶保證共享變量對所有線程的可見性,以及禁止指令重排序)。因為無法保證原子性,所以並不能保證線程安全。

線程安全與共享資源
1.局部變量中的基本數據類型(8種)永遠是線程安全的。
2.局部變量中的對象類型只要不會被其他線程訪問到,也是線程安全的。
3.一個對象實例被多個線程同時訪問時,他的成員變量就可能是線程不安全的。

IO流

IO的名稱又來是Input與Output的縮寫,也就是輸入流和輸出流。輸入流用於從源讀取數據,輸出流用於向目標寫數據。

字符流

字符流有兩個抽象類:WriterReader類。
其對應子類FileWriterFileReader可實現文件的讀寫操作。
BufferedWriterBufferedReader能夠提供緩沖區功能,用以提高效率。

字節流

字節流也有兩個抽象類:InputStreamOutputStream類。
其對應子類有FileInputStreamFileOutputStream實現文件讀寫操作。
BufferedInputStreamBufferedOutputStream提供緩沖區功能

推薦讀取文本用字符流,讀取圖片、視頻和圖片等二進制文件用字節流

IO流更詳細的說明:http://www.panchengming.com/2018/06/16/pancm85/

說起IO流,順便談下它的幾個孿生兄弟,NIO、BIO和AIO。

IO:

阻塞的,從硬盤讀取數據時,程序一直等待,數據讀完在繼續操作 。
操作時一次一個字節的讀取數據,一個輸出流一次輸出一個字節數據,一個輸出流一次消耗一個字節數據,數據的讀取和寫入效率不好。
I/O屬於底層操作,性能依賴與系統環境。

NIO:

同步非阻塞I/O,在讀取數據時程序可以繼續執行,讀取玩數據以後,通知當前程序(即硬件的中斷,軟件中的回調),然後程序立即或執行完後處理數據。選擇器(selector)、緩沖(buffer)、管道(channel) 面向塊(緩沖區)。采取“預讀方式”。操作中一步產生或消費一個數據塊,按塊處理數據,同時數據讀取到一個稍後可能會處理的緩沖區,需要時也可在緩沖區前後移動。
方式適用於連接數目多且連接比較短(輕操作)的架構。例如聊天工具。畢竟好用的框架Netty和Mina。

BIO:

同步並阻塞,服務器實現模式為一個連接一個線程,即客戶端有連接請求時服務器端就需要啟動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷,當然可以通過線程池機制改善。
方式適用於連接數目比較小且固定的架構

AIO:

異步非阻塞,服務器實現模式為一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啟動線程進行處理.。
方式使用於連接數目多且連接比較長(重操作)的架構。

簡單的介紹了下這些知識。詳細的可以查看這篇文章:https://blog.csdn.net/huangwenyi1010/article/details/75577091?ref=myread

其它

Java基礎知識的總結篇就介紹到這裏了,以後的博文主要編寫的方向是Java的進階知識了,主要內容為設計模式,源碼解析和並發編程這塊吧!至於後面的這些博文沒有信心能夠寫好,畢竟這些相對於來說還是比較難以理解的。所以以後的這些相關博文我會按照自己的理解寫的,如果寫的不好,還請多多指點!

原創不易,如果感覺不錯,希望給個推薦!您的支持是我寫作的最大動力!
版權聲明:
作者:虛無境
博客園出處:http://www.cnblogs.com/xuwujing
CSDN出處:http://blog.csdn.net/qazwsxpcm    
個人博客出處:http://www.panchengming.com

Java基礎知識回顧之七 ----- 總結篇