Java 多態、內部類、異常、包

一、多態

1. 概述

  • 理解:多態可以理解為事物存在的多種體(表)現形態。
    • 例如:
      • 動物中的貓和狗。
      • 貓這個對象對應的是貓類型,例如:貓 x = new 貓();
      • 同時貓也是動物中的一種,也可以把貓稱為動物,例如:動物 y = new 貓();
      • 動物就是貓和狗這些具體事物中抽取出來的父類型,父類型的引用指向了子類對象。
  • 體現
    1. 父類的引用指向了子類的對象。
    2. 父類的引用也可以接收自己子類的對象。
      • 例如:Animal a = new Cat();
        • 父類型 a 的引用指向了子類的對象。
  • 前提
    1. 類與類之間必須有關系,要么是繼承,要么是實現。
    2. 存在重寫(覆蓋),父類中有方法被子類重寫(覆蓋)。

2. 利與弊

  • 利:提高了程序的可擴展性和后期的可維護性。

  • 弊:只能使用父類中的引用去訪問父類中的成員。

    • 使用了多態,父類型的引用在使用功能時,不能直接調用子類中特有的方法。
      • 例如:Animal a = new Cat();//多態的體現
        • 假設子類 Cat 中有抓老鼠的特有功能,父類型 a 就不能直接調用該功能,可以理解為 Cat 類型向上轉型,提升了。
        • 父類的引用想要調用子類 Cat 中特有的方法,就要將父類的引用強制轉換成子類的類型,向下轉型。例如:Cat c = (Cat)a;
      • 注:
        • 如果父類可以創建對象的話,例如:Animal a = new Animal(); 就不能進行向下轉型了,Cat c = (Cat)a; 這樣編寫代碼在編譯時會報錯,不要出現將父類對象轉換成子類類型。
        • 多態轉換的是父類引用指向了自己子類的對象時,該引用可以被提升,也可以被強制轉換,多態始終都是子類對象在做變化的。
  • 例如:

3. 特點

1. 成員變量

  • 無論編譯還是運行時期,都參考左邊(引用變量)所屬的類。
    • 例如:多態中父類引用調用成員變量時,如果父類和子類有同名的成員變量,被調用的則是父類中的成員變量。

2. 非靜態成員函數

  • 編譯時期:參考引用型變量所屬的類中是否有調用的方法,如果有,編譯通過,如果沒有,編譯失敗。
    • 例如:a.catchMouse();//編譯報錯,這種情況只能通過強制轉換,向下轉型后才可以使用子類中特有的功能。
  • 運行時期:參考對象所屬的類中是否有調用的方法,如果父類中有一個非抽象方法,子類繼承后將其重寫(覆蓋)了,多態運行時,父類的引用調用同名函數時,運行的是父類中的方法。
  • 總而言之:成員函數在多態調用時,編譯看左邊,運行看右邊。

3. 靜態成員函數

  • 無論編譯還是運行時期,都參考左邊,就是父類的引用在調用同名靜態成員函數時,調用的是父類中的靜態成員函數。
    • 原因:
      • 當類一被加載時,靜態成員函數隨類綁定在內存中,不需要創建對象,可以通過類名直接調用靜態成員函數,并且父類中的靜態成員函數一般是不被重寫(覆蓋)的。

      • 類在方法區中的分配:靜態方法區和非靜態方法區(關鍵字 super 和 this 在非靜態方法區中)。

4. 應用

  1. 定義工具類,將共同行為封裝在同一個類中。
  2. 對類型進行抽取(多態的產生)。
  3. 操作同一個父類型,對其中的子類型均可進行操作。
    • 例如:

二、內部類

1. 概述

  • 概述:將一個類定義在另一個類里面,定義在類里面的那個類稱為內部類(內置類、嵌套類)。
  • 理解:當描述事物時,事物的內部還存在事物,事物內的事物使用內部類來描述,印務內部事物在使用外部事物的內容。
    • 例如:定義一個人的類,手、腳、心臟等等都屬于人,這些又各自有自己的功能描述,這時候就可以在人這個描述類中,定義一些描述手、腳、心臟的類,也就是定義一些內部類。
  • 編譯現象:編譯 Java 文件時,如果類中有內部類,生成的 class 文件中會含有 Test$1.class 等等這樣的文件,編譯器會把內部類翻譯為用 $(美元符號)分隔外部類名和內部類名的類文件,這是內部類的一種編譯現象。

2. 訪問規則

  1. 外部類要訪問內部類,必須建立內部類的對象。
  2. 內部類可以直接訪問外部類中的成員(包括私有成員)。
    • 原因:因為內部類中持有外部類的引用。
    • 格式:外部類名.this

3. 訪問格式

  1. 內部類定義在外部類的成員位置,而且非私有時,可以在外部的其它類中直接建立內部類對象。
    • 格式:外部類名.內部類名 變量名 = 外部類對象.內部類對象;
      • 例如:Outer.Inner in = new Outer().new Inner();
    • 內部類定義在外部類的成員位置時,可以被成員修飾符所修飾。
      • 例如:
        • private:內部類在外部類中進行封裝。
        • static:內部類有局部 statci 的特性,內部類被 static 修飾后,只能訪問外部類中的 static 成員。
          • 外部的其它類訪問 static 內部類中靜態成員的格式:外部類名.內部類名.方法名();
            • 例如:Outer.Inner.function();
          • 外部的其它類訪問 static 內部類中非靜態成員的格式:new 外部類名.內部類名().方法名();
            • 例如:new Outer.Inner().function();
    • 注:
      1. 內部類中定義了靜態成員時,該內部類必須是 static 的。
      2. 外部類中的靜態方法訪問內部類時,內部類也必須是 static 的。
      3. 實際開發中,內部類一般定義為 private,很少定義為 public 的。
  2. 內部類定義在局部位置
    1. 不可被成員修飾符所修飾,作用域限定在聲明這個局部內部類的代碼塊中。
      • 例如:public、private、static 等修飾符。
    2. 可以直接訪問外部類中的成員,還持有外部類的引用。
      • 注:內部類不可以訪問所在局部中的非最終變量,只能訪問被 final 修飾的局部變量。

      • 例如:

        • 分析:上述代碼中的打印結果為 7、8,會改變,并沒有因為被 final 所修飾就無法改變,原因是因為類調用方法結束后,被 final 修飾的變量已經從桟內存中消失,類再次調用方法時,已經是另一個變量了,所以可以重新傳值。

4. 匿名內部類

  • 匿名內部類就是內部類的簡寫格式,匿名內部類其實就是一個匿名子類對象,可以理解為帶內容的對象。

  • 格式:new 父類或接口(){定義子類的內容}

  • 定義匿名內部類的前提:

    • 匿名內部類必須是繼承一個類或者實現接口。
      • 特殊情況:所有的類都有一個父類 Object,定義時也可用 Object。
  • 利與弊:

    • 利:簡化書寫。
    • 弊:
      1. 不能做強轉的動作。
      2. 不能直接調用自己的特有方法。
      3. 如果繼承的父類或接口中方法很多時,使用匿名內部類的可閱讀性會非常差,調用也非常麻煩,因此匿名內部類中定義的方法一般不超過3個。
  • 例如:

三、異常

1. 概述

  • 異常是 Java 中的重要機制,使用面向對象的思想進行了封裝,通常使用的是異常類。異常類中描述的就是程序中可能出現的錯誤或者問題。
  • 程序在運行時出現不正常的情況稱為異常。
  • 由來:異常問題也是現實生活中一個具體的事物,可以通過 Java 中類的形式進行描述,并封裝成對象,異常類就是 Java 對不正常的情況進行描述后的對象體現。
  • 程序中可能出現的錯誤或者問題:
    1. 用戶輸入錯誤導致的異常:非法參數、不按正常的使用程序等。
    2. 設備硬件等發生的錯誤的異常:硬盤損壞等。
    3. 物理限制的異常:存儲空間不足、SDCard不存在等。
    4. 代碼錯誤的異常:程序編寫的方法不正確、返回錯誤的參數等。

2. 體系

異常問題的劃分方式

  1. 嚴重的異常問題。
    • 嚴重的異常問題,Java 通過 Error 類進行描述,對于 Error 類一般不編寫針對性的代碼進行處理。
  2. 非嚴重的異常問題。
    • 非嚴重的異常問題,Java 通過 Exception 類進行描述,對于 Exception 類可以使用針對性的代碼進行處理。

        注:無論是 Error 或 Exception 都具有一些共性內容,例如:不正常情況的相關信息、引發異常的原因等。
      

體系

  • Throwable
    • Error//出現重大異常問題。例如:運行的類不存在或者內存溢出等。
    • Exception//運行時出現的異常情況。
      • RuntimeException//特殊的異常類,Exception 的子類,拋出時不需要做聲明。
  • 注:Error 和 Exception 的子類名稱都是以父類名做為后綴。

特點

  1. 異常體系中所有類以及建立的對象都具備可拋性;
  2. 可以被 throw 和 throws 關鍵字所修飾操作;
  3. 只有異常體系才具備這個特點。

3. 分類

編譯時異常

  • 異常在編譯時,如果沒有做任何處理(沒有拋也沒有 try),編譯失敗。
  • 異常被標識,代表可以被處理。

運行時異常

  • 編譯時不需要處理,編譯器不檢查。
  • 異常發生時,Java 建議不處理,讓程序停止。
  • 需要對代碼進行修正。(例如:RuntimeException 以及 RuntimeException 的子類)

4. 處理

  • Java 中提供了特有的語句進行處理:

      try{
          需要檢測的語句;
      }catch(異常類 變量){
          處理異常的語句(方式);
      }finally{
          一定要執行的語句;
      }
    
    • 這些特有語句的處理方式有三種結合情況:

        1. 
            try{
                需要檢測的語句;
            }catch(異常類 變量){
                處理異常的語句(方式);
            }
        2. 
            try{
                需要檢測的語句;
            }finally{
                一定要執行的語句;
            }
        3. 
            try{
                需要檢測的語句;
            }catch(異常類 變量){
                處理異常的語句(方式);
            }finally{
                一定要執行的語句;
            }
      
    • 注:

      1. finally 中定義的一般是關閉資源的代碼,資源使用完后必須釋放。
      2. 如果存在一些功能是必須執行的,可以使用 try{}finally{} 的方式,將必須執行的語句放在 finally 代碼塊中。
      3. finally 只有一種情況是不會執行的,在進入 finally 之前就先執行了 System.exit(0); 時,已經是退出了程序,finally 就不會執行的。
  • throw 和 throws 的用法:

    • throw 定義在函數內,用于拋出異常對象。
    • throws 定義在函數上,用于拋出異常類,可以拋出多個對象,使用 , 隔開即可。
      • 當函數的內容有 throw 拋出異常對象,但沒 try 處理時,必須在函數上聲明,否則會導致編譯失敗。
    • 注:RuntimeException 除外,函數內如果拋出的是 RuntimeException 異常,函數上不需要聲明。
  • 拋出信息的處理:

    • 函數中出現了 throw 拋出異常對象時,要么是在函數內部進行 try 的處理,要么是在函數上聲明,讓函數的調用者去處理。

    • 對于捕獲到的異常對象常見的操作方法:

        getMessage();//獲取異常信息,返回字符串
        toString();//獲取異常類名和異常信息,返回字符串
        printStackTrace();//獲取異常類名、異常信息以及異常在程序中出現的位置,返回值 void,JVM 默認的異常處理機制中,就是調用 PrintStackTrace() 方法來打印異常的堆棧跟蹤信息
        printStackTrace(PrintStream s);//將異常內容保存在日志文件中
      

5. 自定義

  • 對于一些特有的問題,這些特有的問題沒有被 Java 所描述封裝為對象,對于這些特有的問題,可以按照 Java 的面向對象思想將問題進行自定義的異常封裝,這就是自定義異常。
    • 自定義異常類繼承 Exception 或 RuntimeException
      1. 讓自定義異常類具備可拋性。
      2. 讓自定義異常類具備操作異常的共性方法。
    • 如何自定義異常信息?
      • 自定義異常信息可以使用父類已定義好的功能,異常信息傳遞給父類的構造函數,由于父類中已經把異常信息的操作都完成了,子類只需在構造函數中,通過 super 語句將異常信息傳遞給父類,就可以通過 getMessage() 方法獲取自定義的異常信息了。

      • 例如:

        • 說明:定義異常時,如果異常的發生,會導致無法繼續進行運算,則讓自定義異常類繼承 RuntimeException。
      • 注意:自定義異常必須是自定義異常類有繼承關系,一般繼承 Exception。

        • 自定義異常類繼承 Exception 的原因?
          • 異常體系的特點就是異常類和異常對象都具備可拋性,這個可拋性是 Throwable 體系中獨有的特點,只有這個體系中的類和對象才可以被 throw 和 throws 所操作。

6. 好處與原則

好處

  1. 將問題進行封裝。
  2. 將正常流程的代碼和問題處理的代碼分離,便于閱讀。

原則

  1. 處理方式:try 或 throws。
  2. 調用到拋出異常的功能時,需要對所有拋出的異常進行處理,一個 try 可以對應多個 catch。
  3. 多個 catch 時,父類的 catch 需放到最后面,否則編譯會報錯,因為執行了父類的 catch 語句后,其余的 catch 語句將無法執行到。
  4. catch 中需要定義針對性的處理方式,一般不建議簡單的定義 PrintStackTrace 輸出語句,也不建議不做處理。
    1. 如果捕獲的異常在本功能內處理不了的話,可繼續在 catch 中拋出。

      • 例如:

    2. 如果捕獲的異常在本功能內處理不了的話,但并不屬于本功能出現的異常,可以將異常轉換后再拋出。

    3. 如果捕獲的異常在本功能內可以處理的話,但需要將異常產生后和本功能相關的問題提供出去給調用者,可以將異常轉換后再拋出。

      • 例如:

7. 注意事項

  1. 異常問題在內部被解決就無需聲明。
  2. catch 是用于處理異常,如果沒有 catch,就代表異常問題沒有被處理,該異常如果是檢測時異常,就必須聲明。
  3. 子父類重寫(覆蓋)時:
    1. 子類拋出的異常必須是父類異常的子類或者子集。
    2. 父類或接口沒有異常拋出時,子類重寫(覆蓋)出現異常時,只能 try,不能拋。
      • 例如:

四、包(package)

1. 概述

  • Java 中將 package 稱為包,相當于文件夾,包里面一般存放的是類文件。由于在編寫程序時,難免存在類名相同的情況,為了便于對類進行分類管理,Java 便提供了包,以包的形式存放不同的類,在不同的包中可以有相同的類名,只需在調用時連同包名一起即可。
    • 包也是一種封裝的形式。

2. 作用

  1. 為了避免多個類重名的情況,出現多個相同名字的類時,可通過包將其區分,避免沖突。
  2. 對類文件進行分類管理,可以將相關的類放在同個包中。
  3. 包的出現將 Java 的源文件和類文件分離。
  4. 給類提供了多層命名空間。
    • 例如:
      • a 包中的 Demo.class 文件,如果要創建 Demo 對象,在使用時需加上 a.
      • a.Demo demo = new a.Demo();

3. 規則

  1. 包必須寫在程序的第一行,先有包,才知道類文件的存放位置。
  2. 類的全稱:包.類名。
  3. 編譯定義了包的程序文件時,在編譯時需指定包的存放目錄。
    • 例如:javac -d e:\Demo\mypack 類名.java

4. 包與包之間的訪問

  1. 被訪問的包里類的權限必須是 public。
  2. 訪問其它包中的類時,需定義類的全稱:包名.類名。
  3. 包如果不在當前路徑的話,需使用 classpath 設置環境變量,為 JVM 指明路徑。
  4. 類中的成員權限必須是 public 或 protected。
    • 類公有后,被訪問的成員也要公有才能被訪問。

    • protected 是為子類提供的一種權限。

    • 同個包中,protected 只做用為覆蓋。

    • 不同包中的子類可以直接訪問父類中被 protected 權限修飾符所修飾的成員。

    • 四種權限修飾符:

      • 注:由于被 public 所修飾的類名必須與 java 文件名相同,因此在一個 .java 文件中,不允許出現兩個或以上的公有類或接口。

5. 導入(import)

  • 一個程序文件中只有一個 package,可以有多個 import,import 導入的是包中的類,不導入包中的包。
  • import 可以簡化類名,在調用其它包中的類時,需要寫類的全稱,就是連同包名一起書寫,當類存在多層包中時,使用 import 導入后,使用該類時,可以不加包名。
    • 例如:
      • a.b.c.pack.Demo
      • 導入的格式為 import a.b.c.pack.Demo;
      • 使用該類時,可直接寫 Demo
  • 注意事項:
    1. 導入不同包中有想同類時,必須寫類的全稱以做區分,否則會報錯。
    2. 定義包名不能重復,可以使用 url 來定義,url 是唯一的。
      • 例如:package com.java.Demo
    3. 導入包時,如果包中有很多類,可以使用通配符 * 代替包中所有的類,但不建議使用通配符 *,因為這樣會將不需要使用的類一同導入,會占用內存空間,編寫程序時,需要使用包里的哪些類就導入哪些類。

6. jar 包

  • 類越來越多時,可以使用包類封裝。包越來越多時,可以將包進行壓縮,Java 中通過 jar 工具對包進行壓縮,壓縮后的的后綴名為 jar。
  • jar.exe 工具的常用命令:
    • 創建 jar 包
      • jar -cvf mypack.jar mypack
    • 查看 jar 包
      • jar -tvf mypack.jar
    • 解壓縮
      • jar -xvf mypack.jar
    • 自定義 jar 包的清單文件
      • jar -cvfm mypack.jar mypack.mf mypack
  • 好處:
    1. 數據庫、驅動、SSH框架等都是以 jar 包體現的。
    2. 將多個包壓縮為一個 jar 包文件,便于項目攜帶。
    3. 便于使用,只要在 classpath 設置 jar 包的路徑,即可執行 jar 包中的 java 程序。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容

  • 一、繼承 當兩個事物之間存在一定的所屬關系,即就像孩子從父母那里得到遺傳基因一樣,當然,java要遺傳的更完美,這...
    玉圣閱讀 1,061評論 0 2
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,707評論 18 399
  • (一)Java部分 1、列舉出JAVA中6個比較常用的包【天威誠信面試題】 【參考答案】 java.lang;ja...
    獨云閱讀 7,127評論 0 62
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,776評論 18 139
  • 今天刷空間的時候,看到一情侶曬大晚上壓馬路的恩愛照,底下一片評論全是666。我并沒有評論什么,因為此時的我已經飄到...
    暗香晴雪閱讀 666評論 4 2