445
搜狐
Java 筆記04
內部類:
(注:所有使用內部類的地方都可以不用內部類,使用內部類可以使程序更加的簡潔,便於命名規範和劃分層次結構)。
內部類是指在一個外部類的內部再定義一個類。
內部類作為外部類的一個成員,並且依附於外部類而存在的。
內部類可為靜態,可用PROTECTED和PRIVATE修飾。(而外部類不可以:外部類隻能使用PUBLIC和DEFAULT)。
內部類的分類:
成員內部類、
局部內部類、
靜態內部類、
匿名內部類(圖形是要用到,必須掌握)。
① 成員內部類:作為外部類的一個成員存在,與外部類的屬性、方法並列。
內部類和外部類的實例變量可以共存。
在內部類中訪問實例變量:this.屬性
在內部類訪問外部類的實例變量:外部類名.this.屬性。
成員內部類的優點:
⑴內部類作為外部類的成員,可以訪問外部類的私有成員或屬性。(即使將外部類聲明為PRIVATE,但是對於處於其內部的內部類還是可見的。)
⑵用內部類定義在外部類中不可訪問的屬性。這樣就在外部類中實現了比外部類的private還要小的訪問權限。
注意:內部類是一個編譯時的概念,一旦編譯成功,就會成為完全不同的兩類。
對於一個名為outer的外部類和其內部定義的名為inner的內部類。編譯完成後出現outer.class和outer$inner.class兩類。
(編寫一個程序檢驗:在一個TestOuter.java程序中驗證內部類在編譯完成之後,會出現幾個class.)
成員內部類不可以有靜態屬性。(為什麼?)
如果在外部類的外部訪問內部類,使用out.inner.
建立內部類對象時應注意:
在外部類的內部可以直接使用inner s=new inner();(因為外部類知道inner是哪個類,所以可以生成對象。)
而在外部類的外部,要生成(new)一個內部類對象,需要首先建立一個外部類對象(外部類可用),然後在生成一個內部類對象。
Outer.Innerin=Outer.new.Inner()。
錯誤的定義方式:
Outer.Innerin=new Outer.Inner()。
注意:當Outer是一個private類時,外部類對於其外部訪問是私有的,所以就無法建立外部類對象,進而也無法建立內部類對象。
② 局部內部類:在方法中定義的內部類稱為局部內部類。
與局部變量類似,在局部內部類前不加修飾符public和private,其範圍為定義它的代碼塊。
注意:局部內部類不僅可以訪問外部類實例變量,還可以訪問外部類的局部變量(但此時要求外部類的局部變量必須為final)??
在類外不可直接生成局部內部類(保證局部內部類對外是不可見的)。
要想使用局部內部類時需要生成對象,對象調用方法,在方法中才能調用其局部內部類。
③ 靜態內部類:(注意:前三種內部類與變量類似,所以可以對照參考變量)
靜態內部類定義在類中,任何方法外,用static定義。
靜態內部類隻能訪問外部類的靜態成員。
生成(new)一個靜態內部類不需要外部類成員:這是靜態內部類和成員內部類的區別。靜態內部類的對象可以直接生成:
Outer.Innerin=new Outer.Inner();
而不需要通過生成外部類對象來生成。這樣實際上使靜態內部類成為了一個頂級類。
靜態內部類不可用private來進行定義。例子:
對於兩個類,擁有相同的方法:
People
{
run();
}
Machine{
run();
}
此時有一個robot類:
class Robotextends People implement Machine.
此時run()不可直接實現。
注意:當類與接口(或者是接口與接口)發生方法命名衝突的時候,此時必須使用內部類來實現。
用接口不能完全地實現多繼承,用接口配合內部類才能實現真正的多繼承。
④ 匿名內部類(必須掌握):
匿名內部類是一種特殊的局部內部類,它是通過匿名類實現接口。
IA被定義為接口。
IA I=newIA(){};
注:一個匿名內部類一定是在new的後麵,用其隱含實現一個接口或實現一個類,沒有類名,根據多態,我們使用其父類名。
因其為局部內部類,那麼局部內部類的所有限製都對其生效。
匿名內部類是唯一一種無構造方法類。
匿名內部類在編譯的時候由係統自動起名Out$1.class。
如果一個對象編譯時的類型是接口,那麼其運行的類型為實現這個接口的類。
因匿名內部類無構造方法,所以其使用範圍非常的有限。
(下午:)Exception(例外/異常)(教程上的MODEL7)
對於程序可能出現的錯誤應該做出預案。
例外是程序中所有出乎意料的結果。(關係到係統的健壯性)
JAVA會將所有的錯誤封裝成為一個對象,其根本父類為Throwable。
Throwable有兩個子類:Error和Exception。
一個Error對象表示一個程序錯誤,指的是底層的、低級的、不可恢複的嚴重錯誤。此時程序一定會退出,因為已經失去了運行所必須的物理環境。
對於Error錯誤我們無法進行處理,因為我們是通過程序來應對錯誤,可是程序已經退出了。
我們可以處理的Throwable對象中隻有Exception對象(例外/異常)。
Exception有兩個子類:Runtime exception(未檢查異常)
非Runtimeexception(已檢查異常)
(注意:無論是未檢查異常還是已檢查異常在編譯的時候都不會被發現,在編譯的過程中檢查的是程序的語法錯誤,而異常是一個運行時程序出錯的概念。)
在Exception中,所有的非未檢查異常都是已檢查異常,沒有另外的異常!!
未檢查異常是因為程序員沒有進行必要的檢查,因為他的疏忽和錯誤而引起的異常。一定是屬於虛擬機內部的異常(比如空指針)。
應對未檢查異常就是養成良好的檢查習慣。
已檢查異常是不可避免的,對於已檢查異常必須實現定義好應對的方法。
已檢查異常肯定跨越出了虛擬機的範圍。(比如“未找到文件”)
如何處理已檢查異常(對於所有的已檢查異常都要進行處理):
首先了解異常形成的機製:
當一個方法中有一條語句出現了異常,它就會throw(拋出)一個例外對象,然後後麵的語句不會執行返回上一級方法,其上一級方法接受到了例外對象之後,有可能對這個異常進行處理,也可能將這個異常轉到它的上一級。
對於接收到的已檢查異常有兩種處理方式:throws和try方法。
注意:出錯的方法有可能是JDK,也可能是程序員寫的程序,無論誰寫的,拋出一定用throw。
例:public void print() throws Exception.
對於方法a,如果它定義了throwsException。那麼當它調用的方法b返回異常對象時,方法a並不處理,而將這個異常對象向上一級返回,如果所有的方法均不進行處理,返回到主方法,程序中止。(要避免所有的方法都返回的使用方法,因為這樣出現一個很小的異常就會令程序中止)。
如果在方法的程序中有一行throw new Exception(),返回錯誤,那麼其後的程序不執行。因為錯誤返回後,後麵的程序肯定沒有機會執行,那麼JAVA認為以後的程序沒有存在的必要。
對於try……catch格式:
try {可能出現錯誤的代碼塊} catch(exception e){進行處理的代碼} ;
對象變量的聲明
用這種方法,如果代碼正確,那麼程序不經過catch語句直接向下運行;
如果代碼不正確,則將返回的異常對象和e進行匹配,如果匹配成功,則處理其後麵的異常處理代碼。(如果用exception來聲明e的話,因為exception為所有exception對象的父類,所有肯定匹配成功)。處理完代碼後這個例外就完全處理完畢,程序會接著從出現異常的地方向下執行(是從出現異常的地方還是在catch後麵呢?利用程序進行驗證)。最後程序正常退出。
Try中如果發現錯誤,即跳出try去匹配catch,那麼try後麵的語句就不會被執行。
一個try可以跟進多個catch語句,用於處理不同情況。當一個try隻能匹配一個catch。
我們可以寫多個catch語句,但是不能將父類型的exception的位置寫在子類型的excepiton之前,因為這樣父類型肯定先於子類型被匹配,所有子類型就成為廢話。JAVA編譯出錯。
在try,catch後還可以再跟一子句finally。其中的代碼語句無論如何都會被執行(因為finally子句的這個特性,所以一般將釋放資源,關閉連接的語句寫在裏麵)。
如果在程序中書寫了檢查(拋出)exception但是沒有對這個可能出現的檢查結果進行處理,那麼程序就會報錯。
而如果隻有處理情況(try)而沒有相應的catch子句,則編譯還是通不過。
如何知道在編寫的程序中會出現例外呢
1. 調用方法,查看API中查看方法中是否有已檢查錯誤。
2. 在編譯的過程中看提示信息,然後加上相應的處理。
Exception有一個message屬性。在使用catch的時候可以調用:
Catch(IOExceptione){System.out.println(e.message())};
Catch(IOExceptione){e.printStackTrace()};
上麵這條語句回告訴我們出錯類型所曆經的過程,在調試的中非常有用。
開發中的兩個道理:
①如何控製try的範圍:根據操作的連動性和相關性,如果前麵的程序代碼塊拋出的錯誤影響了後麵程序代碼的運行,那麼這個我們就說這兩個程序代碼存在關聯,應該放在同一個try中。
① 對已經查出來的例外,有throw(積極)和try catch(消極)兩種處理方法。
對於try catch放在能夠很好地處理例外的位置(即放在具備對例外進行處理的能力的位置)。如果沒有處理能力就繼續上拋。
當我們自己定義一個例外類的時候必須使其繼承excepiton或者RuntimeException。
Throw是一個語句,用來做拋出例外的功能。
而throws是表示如果下級方法中如果有例外拋出,那麼本方法不做處理,繼續向上拋出。
Throws後跟的是例外類型。
斷言是一種調試工具(assert)
其後跟的是布爾類型的表達式,如果表達式結果為真不影響程序運行。如果為假係統出現低級錯誤,在屏幕上出現assert信息。
Assert隻是用於調試。在產品編譯完成後上線assert代碼就被刪除了。
方法的覆蓋中,如果子類的方法拋出的例外是父類方法拋出的例外的父類型,那麼編譯就會出錯:子類無法覆蓋父類。
結論:子類方法不可比父類方法拋出更多的例外。子類拋出的例外或者與父類拋出的例外一致,或者是父類拋出例外的子類型。或者子類型不拋出例外。
如果父類型無throws時,子類型也不允許出現throws。此時隻能使用try catch。
練習:寫一個方法:int add(int a,int b)
{
return a+b;
}
當a+b=100;拋出100為異常處理。最後更新:2017-04-02 16:47:44