閱讀445 返回首頁    go 搜狐


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

  上一篇:go Java正則表達式(一)、抓取網頁email地址實例
  下一篇:go J2EE中引入jstl表達式的時候找不到路徑