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. 匿名內部類是省略了【實現類/子類名稱】,但是匿名對象是省略了【對象名稱】

      強調:匿名內部類和匿名對象不是一回事!!!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章