1. 程式人生 > >JavaSE基礎【吐血整理彙總】

JavaSE基礎【吐血整理彙總】

1. 方法

1.1 定義方法的完整格式
  • 定義方法的完整格式:

    修飾符 返回值型別 方法名稱(引數型別 引數名稱, ...) {
        方法體
        return 返回值;
    }
    
    1. 修飾符:現階段的固定寫法,public static
    2. 返回值型別:也就是方法最終產生的資料結果是什麼型別
    3. 方法名稱:方法的名字,規則和變數一樣,小駝峰
    4. 引數型別:進入方法的資料是什麼型別
    5. 引數名稱:進入方法的資料對應的變數名稱

      PS:引數如果有多個,使用逗號進行分隔
    6. 方法體:方法需要做的事情,若干行程式碼
    7. return:兩個作用,第一停止當前方法,第二將後面的返回值還給呼叫處
    8. 返回值:也就是方法執行後最終產生的資料結果

      注意:return後面的“返回值”,必須和方法名稱前面的“返回值型別”,保持對應。
  • 定義一個兩個int數字相加的方法。三要素:

    • 返回值型別:int
    • 方法名稱:sum
    • 引數列表:int a, int b
  • 方法的三種呼叫格式。

    1. 單獨呼叫:方法名稱(引數);
    2. 列印呼叫:System.out.println(方法名稱(引數));
    3. 賦值呼叫:資料型別 變數名稱 = 方法名稱(引數);

注意:此前學習的方法,返回值型別固定寫為void,這種方法只能夠單獨呼叫,不能進行列印呼叫或者賦值呼叫。

1.2 有無引數的方法
  • 有引數:小括號當中有內容,當一個方法需要一些資料條件,才能完成任務的時候,就是有引數。

    例如兩個數字相加,必須知道兩個數字是各自多少,才能相加。
  • 無引數:小括號當中留空。一個方法不需要任何資料條件,自己就能獨立完成任務,就是無引數。

    例如定義一個方法,列印固定10次HelloWorld。
1.3 使用方法注意事項
  1. 方法應該定義在類當中,但是不能在方法當中再定義方法。不能巢狀。
  2. 方法定義的前後順序無所謂。
  3. 方法定義之後不會執行,如果希望執行,一定要呼叫:單獨呼叫、列印呼叫、賦值呼叫。
  4. 如果方法有返回值,那麼必須寫上“return 返回值;”,不能沒有。
  5. return後面的返回值資料,必須和方法的返回值型別,對應起來。
  6. 對於一個void沒有返回值的方法,不能寫return後面的返回值,只能寫return自己。
  7. 對於void方法當中最後一行的return可以省略不寫。
  8. 一個方法當中可以有多個return語句,但是必須保證同時只有一個會被執行到,兩個return不能連寫。
1.4 方法的過載
  • 對於功能類似的方法來說,因為引數列表不一樣,卻需要記住那麼多不同的方法名稱,太麻煩。
  • 方法的過載(Overload):多個方法的名稱一樣,但是引數列表不一樣。
    • 好處:只需要記住唯一一個方法名稱,就可以實現類似的多個功能。
  1. 方法過載與下列因素相關:
    1. 引數個數不同
    2. 引數型別不同
    3. 引數的多型別順序不同
  2. 方法過載與下列因素無關:
    1. 與引數的名稱無關
    2. 與方法的返回值型別無關

2. 陣列

2.1 陣列的概念與特點
  • 陣列的概念:是一種容器,可以同時存放多個數據值。
  • 陣列的特點:
    • 陣列是一種引用資料型別
    • 陣列當中的多個數據,型別必須統一
    • 陣列的長度在程式執行期間不可改變
  • 陣列的初始化:在記憶體當中建立一個數組,並且向其中賦予一些預設值。
    • 兩種常見的初始化方式:
    1. 動態初始化(指定長度)
    2. 靜態初始化(指定內容)
  • 動態初始化陣列的格式:
    資料型別[] 陣列名稱 = new 資料型別[陣列長度];
    • 解析含義:
    1. 左側資料型別:也就是陣列當中儲存的資料,全都是統一的什麼型別
    2. 左側的中括號:代表我是一個數組
    3. 左側陣列名稱:給陣列取一個名字
    4. 右側的new:代表建立陣列的動作
    5. 右側資料型別:必須和左邊的資料型別保持一致
    6. 右側中括號的長度:也就是陣列當中,到底可以儲存多少個數據,是一個int數字
2.2 動態初始化與靜態初始化
  • 動態初始化(指定長度):在建立陣列的時候,直接指定陣列當中的資料元素個數。
  • 靜態初始化(指定內容):在建立陣列的時候,不直接指定資料個數多少,而是直接將具體的資料內容進行指定。
  • 靜態初始化基本格式:
    • 資料型別[] 陣列名稱 = new 資料型別[] { 元素1, 元素2, … };
  • 注意事項:
    • 雖然靜態初始化沒有直接告訴長度,但是根據大括號裡面的元素具體內容,也可以自動推算出來長度。
2.3 靜態初始化格式
  • 使用靜態初始化陣列的時候,格式還可以省略一下。
  • 標準格式:
    • 資料型別[] 陣列名稱 = new 資料型別[] { 元素1, 元素2, … };
  • 省略格式:
    • 資料型別[] 陣列名稱 = { 元素1, 元素2, … };
  • 注意事項:
    1. 靜態初始化沒有直接指定長度,但是仍然會自動推算得到長度。
    2. 靜態初始化標準格式可以拆分成為兩個步驟。
    3. 動態初始化也可以拆分成為兩個步驟。
    4. 靜態初始化一旦使用省略格式,就不能拆分成為兩個步驟了。
  • 使用建議:
    • 如果不確定陣列當中的具體內容,用動態初始化;否則,已經確定了具體的內容,用靜態初始化。
2.4 陣列索引
  • 陣列的索引編號從0開始,一直到“陣列的長度-1”為止。
  • 如果訪問陣列元素的時候,索引編號並不存在,那麼將會發生
    陣列索引越界異常
    ArrayIndexOutOfBoundsException
  • 原因:索引編號寫錯了。
    解決:修改成為存在的正確索引編號。

3. 面向物件

面向過程:當需要實現一個功能的時候,每一個具體的步驟都要親力親為,詳細處理每一個細節。
面向物件:當需要實現一個功能的時候,不關心具體的步驟,而是找一個已經具有該功能的人,來幫我做事兒。
3.1 new物件
  • 通常情況下,一個類並不能直接使用,需要根據類建立一個物件,才能使用。
  1. 導包:也就是指出需要使用的類,在什麼位置。

    import 包名稱.類名稱;

    import cn.itcast.day06.demo01.Student;

    對於和當前類屬於同一個包的情況,可以省略導包語句不寫。
  2. 建立,格式:

    類名稱 物件名 = new 類名稱();

    Student stu = new Student();
  3. 使用,分為兩種情況:

    使用成員變數:物件名.成員變數名

    使用成員方法:物件名.成員方法名(引數)

    (也就是,想用誰,就用物件名點兒誰。)
  • 注意事項:
    • 如果成員變數沒有進行賦值,那麼將會有一個預設值,規則和陣列一樣。
3.2 區域性變數和成員變數
  1. 定義的位置不一樣【重點】

    區域性變數:在方法的內部

    成員變數:在方法的外部,直接寫在類當中

  2. 作用範圍不一樣【重點】

    區域性變數:只有方法當中才可以使用,出了方法就不能再用

    成員變數:整個類全都可以通用。

  3. 預設值不一樣【重點】

    區域性變數:沒有預設值,如果要想使用,必須手動進行賦值

    成員變數:如果沒有賦值,會有預設值,規則和陣列一樣

  4. 記憶體的位置不一樣(瞭解)

    區域性變數:位於棧記憶體

    成員變數:位於堆記憶體

  5. 生命週期不一樣(瞭解)

    區域性變數:隨著方法進棧而誕生,隨著方法出棧而消失

    成員變數:隨著物件建立而誕生,隨著物件被垃圾回收而消失

3.3 面向物件三大特徵
  • 面向物件三大特徵:封裝、繼承、多型
  • 封裝性在Java當中的體現:
    1. 方法就是一種封裝
    2. 關鍵字private也是一種封裝
  • 封裝就是將一些細節資訊隱藏起來,對於外界不可見。
3.4 封裝
  • 問題描述:定義Person的年齡時,無法阻止不合理的數值被設定進來。
  • 解決方案:用private關鍵字將需要保護的成員變數進行修飾。
  • 一旦使用了private進行修飾,那麼本類當中仍然可以隨意訪問。
    但是!超出了本類範圍之外就不能再直接訪問了。
  • 間接訪問private成員變數,就是定義一對兒Getter/Setter方法
  • 必須叫setXxx或者是getXxx命名規則。
    • 對於Getter來說,不能有引數,返回值型別和成員變數對應;
    • 對於Setter來說,不能有返回值,引數型別和成員變數對應。
3.5 構造方法
  • 構造方法是專門用來建立物件的方法,當我們通過關鍵字new來建立物件時,其實就是在呼叫構造方法。
  • 格式:
    public 類名稱(引數型別 引數名稱) {
        方法體
    }
    
  • 注意事項:
    1. 構造方法的名稱必須和所在的類名稱完全一樣,就連大小寫也要一樣
    2. 構造方法不要寫返回值型別,連void都不寫
    3. 構造方法不能return一個具體的返回值
    4. 如果沒有編寫任何構造方法,那麼編譯器將會預設贈送一個構造方法,沒有引數、方法體什麼事情都不做。
      public Student() {}
    5. 一旦編寫了至少一個構造方法,那麼編譯器將不再贈送。
    6. 構造方法也是可以進行過載的。
      過載:方法名稱相同,引數列表不同。
3.6 Java Bean
  • 一個標準的類通常要擁有下面四個組成部分:
    1. 所有的成員變數都要使用private關鍵字修飾
    2. 為每一個成員變數編寫一對兒Getter/Setter方法
    3. 編寫一個無引數的構造方法
    4. 編寫一個全引數的構造方法
  • 這樣標準的類也叫做Java Bean

4. Scanner類

  • Scanner類的功能:可以實現鍵盤輸入資料,到程式當中。
  • 引用型別的一般使用步驟:
    1. 導包

      import 包路徑.類名稱;

      如果需要使用的目標類,和當前類位於同一個包下,則可以省略導包語句不寫。

      只有java.lang包下的內容不需要導包,其他的包都需要import語句。
    2. 建立

      類名稱 物件名 = new 類名稱();
    3. 使用

      物件名.成員方法名()
  • 獲取鍵盤輸入的一個int數字:int num = sc.nextInt();
  • 獲取鍵盤輸入的一個字串:String str = sc.next();
4.1 new物件格式
  • 建立物件的標準格式:
    • 類名稱 物件名 = new 類名稱();
  • 匿名物件就是隻有右邊的物件,沒有左邊的名字和賦值運算子。
    • new 類名稱();
  • 注意事項:匿名物件只能使用唯一的一次,下次再用不得不再建立一個新物件。
  • 使用建議:如果確定有一個物件只需要使用唯一的一次,就可以用匿名物件。

5. Random類

  • Random類用來生成隨機數字。使用起來也是三個步驟:
  1. 導包

    import java.util.Random;
  2. 建立

    Random r = new Random(); // 小括號當中留空即可
  3. 使用

    獲取一個隨機的int數字(範圍是int所有範圍,有正負兩種):int num = r.nextInt()

    獲取一個隨機的int數字(引數代表了範圍,左閉右開區間):int num = r.nextInt(3)

    實際上代表的含義是:[0,3),也就是0~2

6. 陣列與集合的區別

  • 陣列的長度不可以發生改變。
  • 但是ArrayList集合的長度是可以隨意變化的。
  • 對於ArrayList來說,有一個尖括號代表泛型。
    • 泛型:也就是裝在集合當中的所有元素,全都是統一的什麼型別。
    • 注意:泛型只能是引用型別,不能是基本型別。
  • 注意事項:
    • 對於ArrayList集合來說,直接列印得到的不是地址值,而是內容。
    • 如果內容是空,得到的是空的中括號:[]

7. 包裝類

  • 如果希望向集合ArrayList當中儲存基本型別資料,必須使用基本型別對應的“包裝類”。
    基本型別 包裝類(引用型別,包裝類都位於java.lang包下)
    byte Byte
    short Short
    int Integer 【特殊】
    long Long
    float Float
    double Double
    char Character 【特殊】
    boolean Boolean
  • 從JDK 1.5+開始,支援自動裝箱、自動拆箱。
    • 自動裝箱:基本型別 --> 包裝型別
    • 自動拆箱:包裝型別 --> 基本型別

8. String類

java.lang.String類代表字串。

API當中說:Java 程式中的所有字串字面值(如 “abc” )都作為此類的例項實現。

其實就是說:程式當中所有的雙引號字串,都是String類的物件。(就算沒有new,也照樣是。)

  • 字串的特點:
    1. 字串的內容永不可變。【重點】
    2. 正是因為字串不可改變,所以字串是可以共享使用的。
    3. 字串效果上相當於是char[]字元陣列,但是底層原理是byte[]位元組陣列。

建立字串的常見3+1種方式。

  • 三種構造方法:
    • public String():建立一個空白字串,不含有任何內容。
    • public String(char[] array):根據字元陣列的內容,來建立對應的字串。
    • public String(byte[] array):根據位元組陣列的內容,來建立對應的字串。
  • 一種直接建立:
    • String str = “Hello”; // 右邊直接用雙引號

      注意:直接寫上雙引號,就是字串物件。
8.1 String類方法使用
  • public int length():獲取字串當中含有的字元個數,拿到字串長度。
  • public String concat(String str):將當前字串和引數字串拼接成為返回值新的字串。
  • public char charAt(int index):獲取指定索引位置的單個字元。(索引從0開始。)
  • public int indexOf(String str):查詢引數字串在本字串當中首次出現的索引位置,如果沒有返回-1值。

  • public String substring(int index):擷取從引數位置一直到字串末尾,返回新字串。
  • public String substring(int begin, int end):擷取從begin開始,一直到end結束,中間的字串。

    備註:[begin,end),包含左邊,不包含右邊。

  • public char[] toCharArray():將當前字串拆分成為字元陣列作為返回值。
  • public byte[] getBytes():獲得當前字串底層的位元組陣列。
  • public String replace(CharSequence oldString, CharSequence newString):

    將所有出現的老字串替換成為新的字串,返回替換之後的結果新字串。

    備註:CharSequence意思就是說可以接受字串型別。

  • public String[] split(String regex):按照引數的規則,將字串切分成為若干部分。

注意事項:

split方法的引數其實是一個“正則表示式”,今後學習。

今天要注意:如果按照英文句點“.”進行切分,必須寫"\\."(兩個反斜槓)

9. static關鍵字

如果一個成員變數使用了static關鍵字,那麼這個變數不再屬於物件自己,而是屬於所在的類。多個物件共享同一份資料。

9.1 static關鍵字注意事項
  • 一旦使用static修飾成員方法,那麼這就成為了靜態方法。靜態方法不屬於物件,而是屬於類的。
  • 如果沒有static關鍵字,那麼必須首先建立物件,然後通過物件才能使用它。
  • 如果有了static關鍵字,那麼不需要建立物件,直接就能通過類名稱來使用它。
  • 無論是成員變數,還是成員方法。如果有了static,都推薦使用類名稱進行呼叫。
    • 靜態變數:類名稱.靜態變數
    • 靜態方法:類名稱.靜態方法()
  • 注意事項:
    • 靜態不能直接訪問非靜態。

      原因:因為在記憶體當中是【先】有的靜態內容,【後】有的非靜態內容。

      “先人不知道後人,但是後人知道先人。”
    • 靜態方法當中不能用this。

      原因:this代表當前物件,通過誰呼叫的方法,誰就是當前物件。
9.2 靜態程式碼塊
  • 靜態程式碼塊的格式是:
    public class 類名稱 {
        static {
            // 靜態程式碼塊的內容
        }
    }
    
  • 特點:當第一次用到本類時,靜態程式碼塊執行唯一的一次。

    靜態內容總是優先於非靜態,所以靜態程式碼塊比構造方法先執行。
  • 靜態程式碼塊的典型用途:
    用來一次性地對靜態成員變數進行賦值。

10. Math類

  • java.util.Math類是數學相關的工具類,裡面提供了大量的靜態方法,完成與數學運算相關的操作。

public static double abs(double num):獲取絕對值。有多種過載。

public static double ceil(double num):向上取整。

public static double floor(double num):向下取整。

public static long round(double num):四捨五入。

  • Math.PI代表近似的圓周率常量(double)。

11. 繼承

  • 在繼承的關係中,“子類就是一個父類”。也就是說,子類可以被當做父類看待。
    • 例如父類是員工,子類是講師,那麼“講師就是一個員工”。關係:is-a。
  • 定義父類的格式:(一個普通的類定義)
    public class 父類名稱 {
        // ...
    }
    
  • 定義子類的格式:
    public class 子類名稱 extends 父類名稱 {
    // ...
    }
    
11.1 繼承訪問成員變數
  • 在父子類的繼承關係當中,如果成員變數重名,則建立子類物件時,訪問有兩種方式:
    • 直接通過子類物件訪問成員變數:
      • 等號左邊是誰,就優先用誰,沒有則向上找。
    • 間接通過成員方法訪問成員變數:
      • 該方法屬於誰,就優先用誰,沒有則向上找。
11.2 繼承中變數的訪問
  • 區域性變數: 直接寫成員變數名
  • 本類的成員變數: this.成員變數名
  • 父類的成員變數: super.成員變數名
11.3 繼承中方法重寫
  • 在父子類的繼承關係當中,建立子類物件,訪問成員方法的規則:
    • 建立的物件是誰,就優先用誰,如果沒有則向上找。
  • 注意事項:
    • 無論是成員方法還是成員變數,如果沒有都是向上找父類,絕對不會向下找子類的。
  • 重寫(Override)
    • 概念:在繼承關係當中,方法的名稱一樣,引數列表也一樣。
    • 重寫(Override):方法的名稱一樣,引數列表【也一樣】。覆蓋、覆寫。
    • 方法的覆蓋重寫特點:建立的是子類物件,則優先用子類方法。
  • 過載(Overload):方法的名稱一樣,引數列表【不一樣】。
11.4 方法覆蓋重寫的注意事項
  1. 必須保證父子類之間方法的名稱相同,引數列表也相同。
    • @Override:寫在方法前面,用來檢測是不是有效的正確覆蓋重寫。
    • 這個註解就算不寫,只要滿足要求,也是正確的方法覆蓋重寫。
  2. 子類方法的返回值必須【小於等於】父類方法的返回值範圍。
    • 小擴充套件提示:java.lang.Object類是所有類的公共最高父類(祖宗類),java.lang.String就是Object的子類。
  3. 子類方法的許可權必須【大於等於】父類方法的許可權修飾符。
    • 小擴充套件提示:public > protected > (default) > private
    • 備註:(default)不是關鍵字default,而是什麼都不寫,留空。
11.5 繼承中構造方法訪問
  • 繼承關係中,父子類構造方法的訪問特點:
    1. 子類構造方法當中有一個預設隱含的“super()”呼叫,所以一定是先呼叫的父類構造,後執行的子類構造。
    2. 子類構造可以通過super關鍵字來呼叫父類過載構造。
    3. super的父類構造呼叫,必須是子類構造方法的第一個語句。不能一個子類構造呼叫多次super構造。
  • 總結:
    • 子類必須呼叫父類構造方法,不寫則贈送super();
    • 寫了則用寫的指定的super呼叫,super只能有一個,還必須是第一個。

12. 抽象

  • 抽象方法:就是加上abstract關鍵字,然後去掉大括號,直接分號結束。
  • 抽象類:抽象方法所在的類,必須是抽象類才行。在class之前寫上abstract即可。
  • 如何使用抽象類和抽象方法:
    1. 不能直接建立new抽象類物件。
    2. 必須用一個子類來繼承抽象父類。
    3. 子類必須覆蓋重寫抽象父類當中所有的抽象方法。

      覆蓋重寫(實現):子類去掉抽象方法的abstract關鍵字,然後補上方法體大括號。
    4. 建立子類物件進行使用。

13. 介面

  • 介面就是多個類的公共規範。
  • 介面是一種引用資料型別,最重要的內容就是其中的:抽象方法。
  • 如何定義一個介面的格式:
    public interface 介面名稱 {
        // 介面內容
    }
    
  • 備註:換成了關鍵字interface之後,編譯生成的位元組碼檔案仍然是:.java --> .class。
  • 如果是Java 7,那麼介面中可以包含的內容有:
    1. 常量
    2. 抽象方法
  • 如果是Java 8,還可以額外包含有:
    3. 預設方法
    4. 靜態方法
  • 如果是Java 9,還可以額外包含有:
    5. 私有方法
  • 介面使用步驟:
    1. 介面不能直接使用,必須有一個“實現類”來“實現”該介面。

      格式:
      public class 實現類名稱 implements 介面名稱 {
          // ...
      }
      
    2. 介面的實現類必須覆蓋重寫(實現)介面中所有的抽象方法。

      實現:去掉abstract關鍵字,加上方法體大括號。
    3. 建立實現類的物件,進行使用。
  • 注意事項:
    • 如果實現類並沒有覆蓋重寫介面中所有的抽象方法,那麼這個實現類自己就必須是抽象類。
13.1 介面實現重點
  1. 介面的預設方法,可以通過介面實現類物件,直接呼叫。
  2. 介面的預設方法,也可以被介面實現類進行覆蓋重寫。
13.2 介面中靜態方法的呼叫
  • 注意事項:不能通過介面實現類的物件來呼叫介面當中的靜態方法。
  • 正確用法:通過介面名稱,直接呼叫其中的靜態方法。
  • 格式:
    • 介面名稱.靜態方法名(引數);
13.3 介面中定義抽象方法
  • 在任何版本的Java中,介面都能定義抽象方法。
  • 格式:
    public abstract 返回值型別 方法名稱(引數列表);
  • 注意事項:
    1. 介面當中的抽象方法,修飾符必須是兩個固定的關鍵字:public abstract
    2. 這兩個關鍵字修飾符,可以選擇性地省略。(今天剛學,所以不推薦。)
    3. 方法的三要素,可以隨意定義。
13.4 介面中的常量
  • 介面當中也可以定義“成員變數”,但是必須使用public static final三個關鍵字進行修飾。
  • 從效果上看,這其實就是介面的【常量】。
  • 格式:
    public static final 資料型別 常量名稱 = 資料值;
  • 備註:
    一旦使用final關鍵字進行修飾,說明不可改變。
  • 注意事項:
    1. 介面當中的常量,可以省略public static final,注意:不寫也照樣是這樣。
    2. 介面當中的常量,必須進行賦值;不能不賦值。
    3. 介面中常量的名稱,使用完全大寫的字母,用下劃線進行分隔。(推薦命名規則)
13.5 介面定義預設方法
  • 從Java 8開始,接口裡允許定義預設方法。
  • 格式
    public default 返回值型別 方法名稱(引數列表) {
        方法體
    }
    
  • 備註:介面當中的預設方法,可以解決介面升級的問題。
  • 【私有方法】
    • 問題描述:
      • 我們需要抽取一個共有方法,用來解決兩個預設方法之間重複程式碼的問題。
      • 但是這個共有方法不應該讓實現類使用,應該是私有化的。
    • 解決方案:
      • 從Java 9開始,介面當中允許定義私有方法。
      1. 普通私有方法,解決多個預設方法之間重複程式碼問題
        • 格式
        private 返回值型別 方法名稱(引數列表) {
            方法體
        }
        
      2. 靜態私有方法,解決多個靜態方法之間重複程式碼問題
        • 格式:
        private static 返回值型別 方法名稱(引數列表) {
            方法體
        }
        
13.6 介面定義靜態方法
  • 從Java 8開始,介面當中允許定義靜態方法。
  • 格式:
    public static 返回值型別 方法名稱(引數列表) {
        方法體
    }
    
  • 提示:就是將abstract或者default換成static即可,帶上方法體。
13.7 介面使用注意事項
  1. 介面是沒有靜態程式碼塊或者構造方法的。
  2. 一個類的直接父類是唯一的,但是一個類可以同時實現多個介面。
    • 格式:
    public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
        // 覆蓋重寫所有抽象方法
    }
    
  3. 如果實現類所實現的多個介面當中,存在重複的抽象方法,那麼只需要覆蓋重寫一次即可。
  4. 如果實現類沒有覆蓋重寫所有介面當中的所有抽象方法,那麼實現類就必須是一個抽象類。
  5. 如果實現類鎖實現的多個介面當中,存在重複的預設方法,那麼實現類一定要對衝突的預設方法進行覆蓋重寫。
  6. 一個類如果直接父類當中的方法,和介面當中的預設方法產生了衝突,優先用父類當中的方法。
13.8 類與介面的關係
  1. 類與類之間是單繼承的。直接父類只有一個。
  2. 類與介面之間是多實現的。一個類可以實現多個介面。
  3. 介面與介面之間是多繼承的。
  • 注意事項:
    1. 多個父介面當中的抽象方法如果重複,沒關係。
    2. 多個父介面當中的預設方法如果重複,那麼子介面必須進行預設方法的覆蓋重寫,【而且帶著default關鍵字】。

14. 多型

  • 程式碼當中體現多型性,其實就是一句話:父類引用指向子類物件。
  • 格式:

    父類名稱 物件名 = new 子類名稱();

    或者:

    介面名稱 物件名 = new 實現類名稱();
14.1 多型訪問
  • 在多型的程式碼當中,成員方法的訪問規則是:
    • 看new的是誰,就優先用誰,沒有則向上找。
  • 口訣:編譯看左邊,執行看右邊。
  • 對比一下:
    • 成員變數:編譯看左邊,執行還看左邊。
    • 成員方法:編譯看左邊,執行看右邊。
14.2 向上向下轉型
  • 向上轉型一定是安全的,沒有問題的,正確的。但是也有一個弊端:
    • 物件一旦向上轉型為父類,那麼就無法呼叫子類原本特有的內容。
  • 解決方案:用物件的向下轉型【還原】。

15. final關鍵字

  • final關鍵字代表最終、不可改變的。
  • 常見四種用法:
    1. 可以用來修飾一個類
    2. 可以用來修飾一個方法
    3. 還可以用來修飾一個區域性變數
    4. 還可以用來修飾一個成員變數
15.1 final修飾方法
  • 當final關鍵字用來修飾一個方法的時候,這個方法就是最終方法,也就是不能被覆蓋重寫。
  • 格式:
    修飾符 final 返回值型別 方法名稱(引數列表) {
        // 方法體
    }
    
  • 注意事項:
    • 對於類、方法來說,abstract關鍵字和final關鍵字不能同時使用,因為矛盾。
15.2 final修飾類
  • 當final關鍵字用來修飾一個類的時候,格式:
    public final class 類名稱 {
        // ...
    }
    
  • 含義:當前這個類不能有任何的子類。(太監類)
  • 注意:一個類如果是final的,那麼其中所有的成員方法都無法進行覆蓋重寫(因為沒兒子。)
15.3 final修飾成員變數
  • 對於成員變數來說,如果使用final關鍵字修飾,那麼這個變數也照樣是不可變。
  1. 由於成員變數具有預設值,所以用了final之後必須手動賦值,不會再給預設值了。
  2. 對於final的成員變數,要麼使用直接賦值,要麼通過構造方法賦值。二者選其一。
  3. 必須保證類當中所有過載的構造方法,都最終會對final的成員變數進行賦值。

16. Java中有四種許可權修飾符

範圍 public protected (default) private
同一個類(我自己) YES YES YES YES
同一個包(我鄰居) YES YES YES NO
不同包子類(我兒子) YES YES NO NO
不同包非子類(陌生人) YES NO NO NO

注意事項:(default)並不是關鍵字“default”,而是根本不寫。

17. 內部類

  • 如果一個事物的內部包含另一個事物,那麼這就是一個類內部包含另一個類。
    • 例如:身體和心臟的關係。又如:汽車和發動機的關係。
  • 分類:
    1. 成員內部類
    2. 區域性內部類(包含匿名內部類)
  • 成員內部類的定義格式:
    修飾符 class 外部類名稱 {
        修飾符 class 內部類名稱 {
            // ...
        }
        // ...
    }
    

注意:內用外,隨意訪問;外用內,需要內部類物件。

17.1 成員內部類
  • 如何使用成員內部類?有兩種方式:
    1. 間接方式:在外部類的方法當中,使用內部類;然後main只是呼叫外部類的方法。
    2. 直接方式,公式:

      類名稱 物件名 = new 類名稱();

【外部類名稱.內部類名稱 物件名 = new 外部類名稱().new 內部類名稱();】

17.2 區域性內部類1
  • 區域性內部類,如果希望訪問所在方法的區域性變數,那麼這個區域性變數必須是【有效final的】。
  • 備註:從Java 8+開始,只要區域性變數事實不變,那麼final關鍵字可以省略。
  • 原因:
    1. new出來的物件在堆記憶體當中。
    2. 區域性變數是跟著方法走的,在棧記憶體當中。
    3. 方法執行結束之後,立刻出棧,區域性變數就會立刻消失。
    4. 但是new出來的物件會在堆當中持續存在,直到垃圾回收消失。
17.3 區域性內部類2
  • 如果一個類是定義在一個方法內部的,那麼這就是一個區域性內部類。
  • “區域性”:只有當前所屬的方法才能使用它,出了這個方法外面就不能用了。
  • 定義格式:
    修飾符 class 外部類名稱 {
        修飾符 返回值型別 外部類方法名稱(引數列表) {
            class 區域性內部類名稱 {
                // ...
            }
        }
    }
    
17.4 類的許可權修飾符
  • public > protected > (default) > private
  • 定義一個類的時候,許可權修飾符規則:
    1. 外部類:public / (default)
    2. 成員內部類:public / protected / (default) / private
    3. 區域性內部類:什麼都不能寫
17.5 匿名內部類
  • 如果介面的實現類(或者是父類的子類)只需要使用唯一的一次,
    那麼這種情況下就可以省略掉該類的定義,而改為使用【匿名內部類】。
  • 匿名內部類的定義格式:
    介面名稱 物件名 = new 介面名稱() {
        // 覆蓋重寫所有抽象方法
    };
    
  • 對格式“new 介面名稱() {…}”進行解析:
    1. new代表建立物件的動作
    2. 介面名稱就是匿名內部類需要實現哪個介面
    3. {…}這才是匿名內部類的內容
  • 另外還要注意幾點問題:
    1. 匿名內部類,在【建立物件】的時候,只能使用唯一一次。

      如果希望多次建立物件,而且類的內容一樣的話,那麼就需要使用單獨定義的實現類了。
    2. 匿名物件,在【呼叫方法】的時候,只能呼叫唯一一次。

      如果希望同一個物件,呼叫多次方法,那麼必須給物件起個名字。
    3. 匿名內部類是省略了【實現類/子類名稱】,但是匿名物件是省略了【物件名稱】

      強調:匿名內部類和匿名物件不是一回事!!!