天天看點

Java基礎文法09-面向對象下-内部類-注解-異常

内部類

将一個類A定義在另一個類B裡面,裡面的那個類A就稱為内部類,B則稱為外部類。

(1)成員内部類:聲明在外部類中方法外

  • 靜态成員内部類
  • 非靜态成員内部類

(2)局部内部類:聲明在外部類的方法體中

  • 有名字的局部内部類
  • 匿名的内部類

靜态内部類

1、文法格式:

【修飾符】 class 外部類 【extends 父類】 【implements 接口們】{

  【其他修飾符】 static class 靜态内部類 【extends 父類】 【implements 接口們】{

   }

}

外部類的權限修飾符:public或預設,其他修飾符:abstract或final

靜态内部類的權限修飾符:四種,其他修飾符:abstract或final + static

2、靜态内部類也是類

(1)可以有自己的父類或父接口

(2)有自己的位元組碼檔案:外部類名$靜态内部類名.class

(3)有自己的成員:沒有限制

隻要在類中可以寫的成員它都可以有,隻有靜态内部類允許有靜态成員。

3、靜态内部類的使用

(1)靜态内部類使用外部類的成員時:

有限制:靜态内部類不能使用外部類的非靜态成員

(2)在外部類中使用靜态内部類

使用靜态内部類的靜态成員:直接使用“靜态内部類名."

使用靜态内部類的非靜态成員:使用“靜态内部類的對象."

(3)在外部類的外面使用靜态内部類

前提:這個靜态内部類在外面是可見,否則隻能通過這個靜态内部類的父類或父接口來引用它的對象。

如果可見,使用靜态内部類的靜态成員:直接使用“外部類名.靜态内部類名."

使用靜态内部類的非靜态成員:使用“靜态内部類的對象."

外部類.靜态内部類  對象名 = new  外部類.靜态内部類(【...】);

非靜态内部類

1、文法結構:

  【其他修飾符】 class 非靜态内部類 【extends 父類】 【implements 接口們】{

非靜态内部類的權限修飾符:四種,其他修飾符:abstract或final

2、非靜态内部類也是類

(2)有自己的位元組碼檔案:外部類名$非靜态内部類名.class

(3)有自己的成員:有限制

不能有靜态成員,除非靜态常量。

3、非靜态内部類的使用

(1)非靜态内部類使用外部類的成員時:沒有限制

(2)在外部類中使用非靜态内部類

在外部類的靜态成員中使用無法使用非靜态内部類的。

在外部類的非靜态成員中使用非靜态内部類,使用“非靜态内部類的對象."

在非靜态内部類的方法中有兩個this對象,一個是外部類的this對象,一個是内部類的this對象

(3)在外部類的外面使用非靜态内部類

前提:這個非靜态内部類在外面是可見,否則隻能通過這個非靜态内部類的父類或父接口來引用它的對象。

如果可見,使用非靜态内部類的非靜态成員:要求必須有外部類的對象的引用

外部類 out = new 外部類(【...】);

外部類.非靜态内部類 對象名 = out.new 非靜态内部類(【...】);

//在實際開發中,在外部類中編寫一個方法來傳回非靜态内部類的對象,然後調用這個方法來擷取非靜态内部類對象

局部内部類

  【修飾符】 傳回值類型 方法名(【形參清單】){

    【abstract或final或沒有】 class 局部内部類 【extends 父類】 【implements 接口們】{

     }

   }

局部内部類沒有權限修飾符,其他修飾符:abstract或final

局部内部類的特點:

  • 和外部類一樣,它隻是定義在外部類的某個方法中的另一個完整的類結構
    • 可以繼承自己的想要繼承的父類,實作自己想要實作的父接口們,和外部類的父類和父接口無關
    • 可以在局部内部類中聲明屬性、方法、構造器等結構,但不包括靜态成員,除非是從父類繼承的或靜态常量
    • 可以使用abstract修飾,是以它也可以被同一個方法的在它後面的其他内部類繼承
    • 可以使用final修飾,表示不能被繼承
    • 編譯後有自己的獨立的位元組碼檔案,隻不過在内部類名前面冠以外部類名、$符号、編号。
      • 這裡有編号是因為同一個外部類中,不同的方法中存在相同名稱的局部内部類
  • 和成員内部類不同的是,它前面不能有權限修飾符等
  • 局部内部類如同局部變量一樣,有作用域
  • 局部内部類中是否能通路外部類的靜态還是非靜态的成員,取決于所在的方法
  • 局部内部類中還可以使用所在方法的局部常量,即用final聲明的局部變量
    • JDK1.8之後,如果某個局部變量在局部内部類中被使用了,自動加final

在外部類中使用局部内部類

有作用域,即隻能在這個方法體中,并且在聲明之後。

在外部類的外面使用局部内部類:不能

在外部類的外面可以得到局部内部類的對象

但是需要通過它的父類或父接口的變量來引用,用方法的傳回值傳回。

匿名内部類

匿名内部類是沒有名字的類,是以在聲明類的同時就建立好了唯一的對象。

匿名内部類的對象一般會三種形式使用它

父類/父接口 變量 = new 父類/父接口(【實參清單】){

  //可以寫方法....

};

new 父類/父接口(【實參清單】){

}.方法(【實參清單】);

方法名(new 父類/父接口(【實參清單】){

});

所有局部内部類的限制都适用于匿名内部類。例如:

  • 在匿名内部類中是否可以使用外部類的非靜态成員變量,看所在方法是否靜态
  • 在匿名内部類中如果需要通路目前方法的局部變量,該局部變量需要加final

思考:這個對象能做什麼呢?

答:(1)調用某個方法(2)指派給父類/父接口的變量,通過多态引用使用這個對象(3)作為某個方法調用的實參

注解

和普通注釋不同:注解的注釋内容是可以被另一段程式讀取的

一個完整的注解應該有三個部分:

(1)聲明: @interface

(2)使用: @注解名 或 @注解名(....)

(3)讀取:

  • SOURCE:隻能由編譯器讀取
  • CLASS:可以由類加載器讀取
  • RUNTIME:可以通過反射的代碼在運作時讀取

系統預定義的三個最基本的注解

1、@Override

用于檢測被修飾的方法為有效的重寫方法,如果不是,則報編譯錯誤!

隻能标記在方法上。

2、@Deprecated

用于表示被标記的資料已經過時,不建議使用。

可以用于修飾 屬性、方法、構造、類、包、局部變量、參數。

3、@SuppressWarnings

抑制編譯警告。

可以用于修飾類、屬性、方法、構造、局部變量、參數

格式:

@SuppressWarnings("all")
@SuppressWarnings("uncheck")
@SuppressWarnings({"unused","uncheck"})      

文檔注釋

  • @author 标明開發該類子產品的作者,多個作者之間使用,分割
  • @version 标明該類子產品的版本
  • @see 參考轉向,也就是相關主題
  • @since 從哪個版本開始增加的
  • @param 對方法中某參數的說明,如果沒有參數就不能寫
  • @return 對方法傳回值的說明,如果方法的傳回值類型是void就不能寫
  • @throws/@exception 對方法可能抛出的異常進行說明 ,如果方法沒有用throws顯式抛出的異常就不能寫
    • 其中 @param @return 和 @exception 這三個标記都是隻用于方法的。
    • @param的格式要求:@param 形參名 形參類型 形參說明
    • @return 的格式要求:@return 傳回值類型 傳回值說明
    • @exception 的格式要求:@exception 異常類型 異常說明
    • @param和@exception可以并列多個

javadoc.exe就是這些注解的資訊處理流程。

如果導出時有亂碼問題,可以指定字元編碼

-docencoding UTF-8

-encoding UTF-8

-charset UTF-8

JUnit單元測試

  • @Test:标記在非靜态的測試方法上。
  • @BeforeClass:标記在靜态方法上。因為這個方法隻執行一次。在所有方法@Test方法之前執行。
  • @AfterClass:标記在靜态方法上。因為這個方法隻執行一次。在所有方法@Test方法完成後執行。
  • @Before:标記在非靜态方法上。在@Test方法前面執行,而且是在每一個@Test方法前面都執行
  • @After:标記在非靜态方法上。在@Test方法後面執行,而且是在每一個@Test方法後面都執行
  • @BeforeClass、@AfterClass、@Before、@After都是配合@Test使用的,單獨使用沒有意義。

元注解

(1)@Target:用于描述注解的使用範圍

  • 可以通過枚舉類型ElementType的10個常量對象來指定

(2)@Retention:用于描述注解的生命周期

  • 可以通過枚舉類型RetentionPolicy的3個常量對象來指定
  • 唯有RUNTIME階段才能被反射讀取到。

(3)@Documented:表明這個注解應該被 javadoc工具記錄。

(4)@Inherited:允許子類繼承父類中的注解

自定義注解

@元注解

【修飾符】 @interface 注解名{

  資料類型 參數名1();

  資料類型 參數名2() default 預設值;

(1)聲明時,類型有要求:

8種基本資料類型、String、枚舉、Class、注解,以及他們的數組

(2)使用時

可以在定義 Annotation 的成員變量時為其指定初始值, 指定成員變量的初始值可使用 default 關鍵字

如果定義的注解含有配置參數,那麼使用時必須指定參數值,除非它有預設值。格式是“參數名 = 參數值”,如果隻有一個參數成員需要指派,且名稱為value,可以省略“value=”

自定義注解必須配上注解的資訊處理流程才有意義。

異常

對于異常,一般有兩種解決方法:一是遇到錯誤就終止程式的運作。另一種方法是由程式員在編寫程式時,就考慮到錯誤的檢測、錯誤消息的提示,以及錯誤的處理。

異常的根類是

java.lang.Throwable

,其下有兩個子類:

java.lang.Error

java.lang.Exception

,平常所說的異常指

java.lang.Exception

Java基礎文法09-面向對象下-内部類-注解-異常

如果要自定義異常,必須繼承Throwable或它的子類

Error:嚴重錯誤Error,無法通過處理的錯誤,隻能事先避免

Exception:表示異常,其它因程式設計錯誤或偶然的外在因素導緻的一般性問題,程式員可以通過代碼的方式糾正,使程式繼續運作,是必須要處理的。

Exception的兩大類:編譯時異常和運作時異常

運作時異常:RuntimeException或它的子類

編譯時異常:除了運作時異常都是編譯時異常

Java異常處理的五個關鍵字:try、catch、finally、throw、throws

1、try:嘗試執行可能會發生異常的代碼

2、catch:嘗試捕獲try中發生的異常

3、finally:無論try中是否發生異常,也無論catch是否可以捕獲異常,也不管try和catch中是否有return語句,都要執行。除非在try或catch中執行了System.exit(0)語句。

4、throw:用于手動抛出異常

5、throws:表示某個方法内部沒有處理xx異常,抛給調用者處理,在方法的簽名中顯式聲明抛出哪些異常

try{

  可能發生異常的代碼

}catch(異常類型 e){

  處理異常的代碼

  //列印,或什麼都不寫,或者其他處理代碼

}finally{

  ...

throw用在方法内,用來抛出一個異常對象,将這個異常對象傳遞到調用者處,并結束目前方法的執行。

throw new 異常類名(參數);

關鍵字throws運用于方法聲明之上,用于表示目前方法不處理異常,而是提醒該方法的調用者來處理異常(抛出異常).

修飾符 傳回值類型 方法名(參數) throws 異常類名1,異常類名2…{   }

在方法中使用try-catch的語句塊來處理異常。

try:該代碼塊中編寫可能産生異常的代碼。

catch:用來進行某種異常的捕獲,實作對捕獲到的異常進行處理。

  • 可以有多個catch塊,按順序比對。
  • 如果多個異常類型有包含關系,那麼小上大下

finally:有一些特定的代碼無論異常是否發生,都需要執行。另外,因為異常會引發程式跳轉,導緻有些語句執行不到。而finally就是解決這個問題的,在finally代碼塊中存放的代碼都是一定會被執行的。

注意:finally不能單獨使用。當隻有在try或者catch中調用退出JVM的相關方法,例如System.exit(0),此時finally才不會執行,否則finally永遠會執行。

一般我們是使用一次捕獲多次處理方式

注意:這種異常處理方式,要求多個catch中的異常不能相同,并且若catch中的多個異常之間有子父類異常的關系,那麼子類異常要求在上面的catch處理,父類異常在下面的catch處理。

  • 運作時異常被抛出可以不處理。即不捕獲也不聲明抛出。
  • 如果finally有return語句,永遠傳回finally中的結果,避免該情況.
  • 如果父類抛出了多個異常,子類重寫父類方法時,抛出和父類相同的異常或者是父類異常的子類或者不抛出異常。
  • 父類方法沒有抛出異常,子類重寫父類該方法時也不可抛出異常。此時子類方法中産生了編譯時異常,隻能捕獲處理,不能聲明抛出

自定義異常

要求:

1、必須繼承Throwable或它的子類,一般繼承Exception或RuntimeException

2、盡量保留兩個構造器:無參和有參(message)

3、加序列化版本ID

4、自定義異常類型的對象隻能使用throw語句抛出

自定義異常最重要的是異常類的名字,當異常出現時,可以根據名字判斷異常類型。

 常見異常清單