java內部類怎么寫
一。內部類基礎
二。深入理解內部類
三。內部類的使用場景和好處
四。常見的與內部類相關的筆試面試題
若有不正之處,請多諒解并歡迎批評指正。
一。內部類基礎
在Java中,可以將一個類定義在另一個類里面或者一個方法里面,這樣的類稱為內部類。廣泛意義上的內部類一般來說包括這四種:成員內部類、局部內部類、匿名內部類和靜態內部類。下面就先來了解一下這四種內部類的用法。
1.成員內部類
成員內部類是最普通的內部類,它的定義為位于另一個類的內部,形如下面的形式:
class Circle { doubleradius = 0; publicCircle( doubleradius) { this.radius = radius; } class Draw { //內部類publicvoiddrawSahpe() { System. out.println( “drawshape”); } } }
這樣看起來,類Draw像是類Circle的一個成員,Circle稱為外部類。成員內部類可以無條件訪問外部類的所有成員屬性和成員方法(包括private成員和靜態成員)。
class Circle { privatedoubleradius = 0; publicstaticintcount = 1; publicCircle( doubleradius) { this.radius = radius; } class Draw { //內部類publicvoiddrawSahpe() { System.out.println(radius); //外部類的private成員System. out.println(count); //外部類的靜態成員} } }
不過要注意的是,當成員內部類擁有和外部類同名的成員變量或者方法時,會發生隱藏現象,即默認情況下訪問的是成員內部類的成員。如果要訪問外部類的同名成員,需要以下面的形式進行訪問:
外部類。 this.成員變量 外部類。 this.成員方法
雖然成員內部類可以無條件地訪問外部類的成員,而外部類想訪問成員內部類的成員卻不是這么隨心所欲了。在外部類中如果要訪問成員內部類的成員,必須先創建一個成員內部類的對象,再通過指向這個對象的引用來訪問:
class Circle { privatedoubleradius = 0; publicCircle( doubleradius) { this.radius = radius; getDrawInstance().drawSahpe(); //必須先創建成員內部類的對象,再進行訪問}privateDraw getDrawInstance() { returnnewDraw(); } class Draw { //內部類publicvoiddrawSahpe() { System. out.println(radius); //外部類的private成員} } }
成員內部類是依附外部類而存在的,也就是說,如果要創建成員內部類的對象,前提是必須存在一個外部類的對象。創建成員內部類對象的一般方式如下:
publicclassTest { publicstaticvoidmain(String[] args) { //第一種方式:Outter outter =newOutter(); Outter.Inner inner = outter. newInner(); //必須通過Outter對象來創建//第二種方式:Outter.Inner inner1 = outter.getInnerInstance(); } } class Outter { privateInner inner = null; publicOutter() { } publicInner getInnerInstance() { if(inner == null) inner =newInner(); returninner; } class Inner { publicInner() { } } }
內部類可以擁有private訪問權限、protected訪問權限、public訪問權限及包訪問權限。比如上面的例子,如果成員內部類Inner用private修飾,則只能在外部類的內部訪問,如果用public修飾,則任何地方都能訪問;如果用protected修飾,則只能在同一個包下或者繼承外部類的情況下訪問;如果是默認訪問權限,則只能在同一個包下訪問。這一點和外部類有一點不一樣,外部類只能被public和包訪問兩種權限修飾。我個人是這么理解的,由于成員內部類看起來像是外部類的一個成員,所以可以像類的成員一樣擁有多種權限修飾。
2.局部內部類
局部內部類是定義在一個方法或者一個作用域里面的類,它和成員內部類的區別在于局部內部類的訪問僅限于方法內或者該作用域內。
classPeople{publicPeople() { } } classMan{publicMan(){ } publicPeople getWoman(){classWomanextendsPeople{//局部內部類intage = 0; } returnnewWoman(); } }
注意,局部內部類就像是方法里面的一個局部變量一樣,是不能有public、protected、private以及static修飾符的。
3.匿名內部類
匿名內部類應該是平時我們編寫代碼時用得最多的,在編寫事件監聽的代碼時使用匿名內部類不但方便,而且使代碼更加容易維護。下面這段代碼是一段Android事件監聽代碼:
scan_bt.setOnClickListener( newOnClickListener() { @OverridepublicvoidonClick(View v) { // TODO Auto-generated method stub} }); history_bt.setOnClickListener(newOnClickListener() { @OverridepublicvoidonClick(View v) { // TODO Auto-generated method stub} });
這段代碼為兩個按鈕設置監聽器,這里面就使用了匿名內部類。這段代碼中的:
newOnClickListener() { @OverridepublicvoidonClick(View v) { // TODO Auto-generated method stub} }
就是匿名內部類的使用。代碼中需要給按鈕設置監聽器對象,使用匿名內部類能夠在實現父類或者接口中的方法情況下同時產生一個相應的對象,但是前提是這個父類或者接口必須先存在才能這樣使用。當然像下面這種寫法也是可以的,跟上面使用匿名內部類達到效果相同。
privatevoidsetListener() { scan_bt.setOnClickListener( newListener1()); history_bt.setOnClickListener( newListener2()); }classListener1implementsView.OnClickListener{@Override publicvoidonClick(View v) { // TODO Auto-generated method stub} }classListener2implementsView.OnClickListener{@Override publicvoidonClick(View v) { // TODO Auto-generated method stub} }
這種寫法雖然能達到一樣的效果,但是既冗長又難以維護,所以一般使用匿名內部類的方法來編寫事件監聽代碼。同樣的,匿名內部類也是不能有訪問修飾符和static修飾符的。
匿名內部類是唯一一種沒有構造器的類。正因為其沒有構造器,所以匿名內部類的使用范圍非常有限,大部分匿名內部類用于接口回調。匿名內部類在編譯的時候由系統自動起名為Outter$1.class。一般來說,匿名內部類用于繼承其他類或是實現接口,并不需要增加額外的方法,只是對繼承方法的實現或是重寫。
4.靜態內部類
靜態內部類也是定義在另一個類里面的類,只不過在類的前面多了一個關鍵字static。靜態內部類是不需要依賴于外部類的,這點和類的靜態成員屬性有點類似,并且它不能使用外部類的非static成員變量或者方法,這點很好理解,因為在沒有外部類的對象的情況下,可以創建靜態內部類的對象,如果允許訪問外部類的非static成員就會產生矛盾,因為外部類的非static成員必須依附于具體的對象。
publicclassTest { publicstaticvoidmain(String[] args) { Outter.Inner inner =newOutter.Inner(); } } class Outter { publicOutter() { } staticclass Inner { publicInner() { } } }
非常好我支持^.^
(0) 0%
不好我反對
(0) 0%