内部類
将一個類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
。

如果要自定義異常,必須繼承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語句抛出
自定義異常最重要的是異常類的名字,當異常出現時,可以根據名字判斷異常類型。