1. 程式人生 > >Java 基礎知識總結--持續更新

Java 基礎知識總結--持續更新

Java是OOP語言,所有的OOP語言都有三個特性:封裝、多型、繼承。

封裝

封裝是一種將程式碼與它所處理的資料結合起來,而不被外界干擾濫用的程式設計機制。
在Java中,基本封裝單元是,資料即欄位,程式碼即方法。

多型

多型是一種允許使用一個介面來訪問一類動作的特性。
在Java中,多型的表現形式為:1、介面的實現;2、繼承父類進行方法重寫(override);3、同一個類中進行方法的過載(overloaded)。

繼承

繼承是一個物件獲得另一個物件的屬性的過程。繼承之所以重要,是因為它支援層級結構類的概念。

物件的型別,決定一類物件的外觀和行為。一個類中可以設定兩種

型別的元素:欄位方法
欄位可以是任意型別的物件(基本型別和引用型別/ps:注意欄位的初始化和區域性變數初始化的區別);方法由名稱、引數、返回值和方法體構成,其中名稱和引數列表合起來稱為方法簽名以用來唯一的標識一個方法。
當建立類時,就是在描述那個類的物件的外觀和行為。

static關鍵字

一個類通過new新建了物件之後,資料儲存空間才會分配,其方法和域才能被外界所使用。
static關鍵字用來解決以下兩種情形:1、只想為某特定域分配單一的儲存空間,而不去考慮究竟要建立多少物件,或者根本不需要建立物件。2、希望某個方法不與包含它的類任何物件關聯在一起。即使沒有建立物件,也可以使用該方法。

static{}(即static塊),會在類被載入的時候執行且僅會被執行一次,一般用來初始化靜態變數和呼叫靜態方法。

抽象類

抽象方法是僅有方法宣告但是沒有方法體的方法。包含抽象方法的類稱為抽象類。抽象類是介於類和介面的中庸之道。

介面

介面是一個完全抽象的類。一方面,一個介面表示:所有實現了該介面的類看起來都像這樣,這建立了類與類之間通訊的協議
另一方面,介面也是其實現類的基類,類可以被向上轉型為藉口型別,它允許通過建立一個能夠被向上轉型為多種基類的型別,來實現某種型別多重繼變種的特性。(一個實現了多種介面的類,其基類可以是其中任意一種。)
既然介面也是類,則滿足類的基本特性:具有欄位和方法。由於介面的協議特性,介面的欄位和方法預設都是public

的。其中欄位還是static final的。
介面支援多繼承。如RunnableFuture介面。

巢狀介面

介面可以巢狀在類或者其他介面中。實際上是一種內部類
由介面的協議特性,介面中的巢狀介面必須是public的。實現該外圍介面無需實現巢狀介面。類中的巢狀介面可以是private的。

向上轉型和向下轉型

繼承

1、 子類可以繼承父類的非private屬性和方法,不包括建構函式。屬性和方法均屬於類的成員,構造方法不是成員。繼承描述了is-a關係,描述了兩個物件的屬性和行為的相似性關聯性。建構函式顧名思義是用來構造一個物件的,是用來為物件的初始化服務的,並不參與物件的屬性和行為的描述。
2、 子類不能繼承父類的private成員,但是如果父類有protected或者public方法可以訪問父類private成員,子類可以通過這些方法訪問private成員。
3、 子類可以擁有自己的屬性和方法。繼承描述了共性,也提供了特殊性的表示方法。
4、 子類可以用自己的方式實現父類的方法—方法的重寫
5、 子類可以實現父類方法的不同版本—方法的過載

物件初始化順序

父類B靜態程式碼塊->子類A靜態程式碼塊->父類B非靜態程式碼塊->父類B建構函式->子類A非靜態程式碼塊->子類A建構函式
當例項化子類物件時,首先要載入父類的class檔案進記憶體,靜態程式碼塊是隨著類的建立而執行,所以父類靜態程式碼塊最先被執行,子類class檔案再被載入,同理靜態程式碼塊被先執行;例項化子類物件要先呼叫父類的構造方法,而呼叫父類構造方法前會先執行父類的非靜態程式碼塊

過載和重寫

方法的簽名:指的是方法的組成結構。具體包括方法的名稱和引數,涵蓋引數的數量,型別以及出現的順序,但是不包括方法的返回值型別、訪問許可權修飾符、丟擲的異常

初步理解:過載和重寫都是多型性的表現。過載是指的同一個方法名稱,但是有不同的方法簽名,存在於繼承和同一個類中。重寫是指方法簽名以及返回型別不變,丟擲的異常應是被重寫方法的子類,但是方法的執行邏輯變了—子類修改了父類的實現邏輯,是為重寫。

方法的重寫(override)兩同兩小一大原則:
方法名相同,引數型別相同
子類返回型別小於等於父類方法返回型別,
子類丟擲異常小於等於父類方法丟擲異常,
子類訪問許可權大於等於父類方法訪問許可權。

try catch finally return

1、不管有木有出現異常,finally塊中程式碼都會執行;
2、當try和catch中有return時,finally仍然會執行;
3、finally是在return語句執行之後,返回之前執行的(此時並沒有返回運算後的值,而是先把要返回的值儲存起來,不管finally中的程式碼怎麼樣,返回的值都不會改變,仍然是之前儲存的值),所以函式返回值是在finally執行前就已經確定了;
4、finally中如果包含return,那麼程式將在這裡返回,而不是try或catch中的return返回,返回值就不是try或catch中儲存的返回值了。
注意:
finally修改的基本型別是不影響返回結果的。(傳值的)
修改list ,map,自定義類等引用型別時,是影響返回結果的。(傳址的)物件也是傳址的

內部類

https://www.cnblogs.com/dolphin0520/p/3811445.html
內部類在外部類中,類比外部類的成員變數
內部類其實和類的屬性沒什麼區別,只是在宣告的時候必須是Outer.Inner a,就像int a 一樣,至於靜態內部類和非靜態內部類new的時候有點區別

Class物件

對應每個類的class檔案,像是每個類的超級管理員。

動態方法分配

動態方法分配機制,通過該機制,對一個被重寫方法的呼叫會在執行時解析,而不是編譯時解析。是java實現執行時多型的機制。具體如:當通過超類引用呼叫被重寫方法時,java會根據在呼叫發生時引用的物件的型別來判斷所要執行的方法。

this關鍵字

this關鍵字只能在方法內部使用,表示對“呼叫方法的那個物件”的引用

class A{
    int i;
    int j;
    public A(int i){}
    public A(int i,int j){
    this(i);//呼叫構造器
    this.j = j;//引用屬性
    }
}

基本資料型別

這裡寫圖片描述

equals()和==

equals()是Object的方法,==是關係操作符,關係操作符計算的結果是一個boolean結果。計算的是運算元的值之間的關係。
對於基本資料型別(不是物件),equals()無法使用,通過==直接比較值。
對於引用資料型別,==和Object物件的equals()方法都是比較的物件的引用

object 的equals()方法:
public boolean equals(Object obj) {
        return (this == obj);
    }

如果想比較物件的內容,需要自己重寫equals()方法。大部分java類庫都實現了equals()方法,以便用來比較物件的內容,而不僅僅是引用。

String 的equals()方法:
public boolean equals(Object anObject) {
        //如果引用相同則兩個String物件內容相同
        if (this == anObject) {
            return true;
        }
        //如果引用不相同,則挨個比較兩個字串物件的字元(比較內容)
        if (anObject instanceof String) {
            String anotherString = (String) anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

靜態內部類和內部類

要想直接建立內部類的物件,必須先使用外部類的物件來建立該內部類物件。在擁有外部類物件之前是不可能建立內部類物件的,因為內部類物件會暗暗連線到建立它的外部類物件上去。
靜態內部類則沒有這個限制,可以直接建立。

public class A{
    public class B{}
    public static class C{}
}
public class Test{
    A a = new A();
    //這裡不可以直接建立內部類B的物件
    //A.B b = new B();
    //正確方式,通過A的例項來建立
    A.B b = a.new B();
    //對於C,可以直接建立
    A.C c = new C();
}

Java引數傳遞

Java中引數傳遞的都是值
對於函式對引數的改變是否會影響原值的問題:

  • 值型別:傳遞值的拷貝,改變引數值不影響原值
  • 引用型別:傳遞引用的拷貝,如果引數指向了不同的例項則引數引用和原引用不相等,如果改變的是例項本身,則引數和原引用相等

equals和hashcode

equals方法用來定義兩個物件例項(注意不是引用)是否相等的規則,可以理解為判斷兩個物件例項是否是一模一樣的例項。

hashcode方法主要用在雜湊表中,物件通過hashcode方法算出物件的雜湊值,再去雜湊表中插入或者查詢。我們知道計算hashcode時是可能存在碰撞情況的,也就是不同的物件(equals),hashcode可能是一樣的;但是兩個物件的hashcode不一樣的話,那麼這兩個物件一定是不相等(equals)的。

集合

List
ArrayList 陣列 與System.arrayCopy
LinkedList 帶頭尾節點的雙向連結串列,可以作為雙端佇列和棧

Map
HashMap
LinkedHashMap Entry帶有前後節點的引用,帶頭結點的雙向連結串列,保持插入順序,或者在插入順序的基礎上再保持訪問順序-每次訪問某個Entry,將該Entry移至連結串列尾部,成為最近最多使用節點(這裡get方法和put方法都是如此,尤其是put方法中key已經存在了,同樣會被移至連結串列尾部,因為recordAccess方法在HashMap中已經寫在put方法裡了)。啟用訪問順序可以作為LRU連結串列使用,需要重寫方法removeEldestEntry設定移除條件(如大小到了某個值),在條件達到時,即移除最近最少訪問節點。

插入順序還是訪問順序,最近最少訪問節點都是連結串列的頭結點,最近最多訪問節點是連結串列尾節點。

TreeMap 紅黑樹 二叉查詢樹 需要比較器
WeakHashMap
ConcurrentHashMap

Set
HashSet 由HashMap支援
LinkedHashSet 由LinkedHashMap支援,遍歷有序
TreeSet 由TreeMap支援,遍歷有序

Queue
PriorityQueue 優先佇列,由陣列和堆支援。堆序性質:樹的根節點小於子節點。堆序性質的維護:在葉子節點插入,上濾保持堆序;在根節點刪除,下濾保持堆序。
另外還有擴容操作,直接增加容量再複製陣列即可。

主要設計模式:模板方法模式、迭代器模式

併發包

AQS、ReentrantLock、ReentrantReadWriteLock、Lock、Condition、LockSupport、synchronized、volatile等

執行緒

定義:Callable、Runnable、Thread、Future、FutureTask、ThreadLocal
執行:Executor、Executors、ExecutorService、ThreadPoolExecutor、ScheduledExecutorService
協同:ForkJoin、CountDownLatch、中斷等

併發容器

ConcurrentHashMap
阻塞佇列:ArrayBlockingQueue LinkedBlockingQueue PriorityQueue(等待通知模式)
非阻塞佇列:ConcurrentLinkedQueue

ThreadLocal

可以將有狀態的Bean轉換為無狀態的Bean,如spring中的DAO,資料庫連線必須是執行緒私有的,無法共享,通過ThreadLocal Connection將連線執行緒私有化。
主要通過Thread類中的ThreadLocalMap發揮作用。每個執行緒都有自己的ThreadLocalMap,其key為ThreadLocal物件,value為設定的值。在呼叫ThreadLocal的get方法獲取值時,都是去當前執行緒的ThreadLocalMap中獲取。

ThreadLocalMap中的Entry是弱引用,其弱引用是key。如果某個執行緒一直不死(執行緒池),ThreadLocalMap中的Entry將永遠得不到回收。通過將key作為弱引用,幫助GC(在set和get方法中都有處理弱引用失效的Entry流程,將他它們清理出map,避免記憶體洩漏)。

key的hashcode值時ThreadLocalMap中的static方法生成的,同一個應用中公用這一個方法生成hashcode。該map由迴圈陣列支援,其處理hash碰撞的方法是線性探測法。