內部類
可以將乙個類的定義放在另乙個類的定義內部,這就是內部類。
內部類是一種非常有用的特性,因為它允許你把一些邏輯相關的類組織在一起,並控制位於內部的類的可視性。
最初,內部類看起來像一種**隱藏機制:將類置於其他類的內部。但是內部類遠不止如此,它了解外圍類,並能與之通訊;而且你用內部類寫出的**更加優雅而清晰,儘管不總是如此。
建立內部類:
將類的定義置於外圍類的裡面
在外圍類的普通方法適用內部類的時候,與適用普通類沒有不同
如果想從外部類的非靜態方法之外的任意位置建立某個內部類的物件,那麼必須像在main()方法中那樣,具體的指明這個物件的型別:outerclassname.innerclassname.
鏈結到外部類
到目前為止,內部類似乎只還有一種名字隱藏和組織**的模組。內部類還有其他用途。當生成乙個內部類的物件時,此物件與製造它的外圍物件之間就有了一種聯絡,所以它能訪問其外圍物件所有的成員,而不需要任何特殊條件,此外,內部類還擁有其外圍類的所有元素的訪問權。
內部類自動擁有對其外圍類所有成員的訪問權。這是如何做到的呢?當某個外圍類的物件建立了乙個內部類物件時,次內部類物件必定會秘密地捕獲乙個指向那個外圍類物件的引用。然後,你在訪問次外圍類的成員時,就是用那個引用來選擇外圍類的成員。
使用.this與.new
public class dothis
public class inner
}public inner inner()
public static void main(string args)
}如果你需要生成對外部類物件的引用,可以使用外部類的名字後面緊跟圓點和this。這樣產生的引用自動地具有正確的型別
public static void main(string args)
有時你可能想要告訴某些其他物件,去建立其某個內部類的物件。要實現此目的,你必須在new表示式中提供對其他外部類物件的引用,這時需要使用.new語法
在擁有外部類物件之前是不可能建立內部類物件的。這時因為內部類物件會暗暗地連線到建立它的外部類物件上。但是,如果你建立的是巢狀類(靜態內部類),那麼它就不需要對外部類物件的引用。
public class parcel3
}class destination
string readlabel()
}public static void main(string args)
}內部類與向上轉型
內部類向上轉型為其基類,尤其是轉型為乙個介面的時候,很有用。
這是因為此內部類——某個介面的實現——能夠完全不可見,並且不可用。所得到的知識指向基類或者介面的而引用,所以能夠很方便的隱藏實現細節。
public class parcel4
}protected class pdestination implements destination
public string readlabel()
}public destination destination(string s)
public contents contents()
}class testparcel
}inte***ce destination
inte***ce contents
parcel4中增加了一些新東西:內部類pcontents是private,所以除了parcel4,沒有人能訪問它。pdestination是protected,所以只有parcel4及其自雷、還有與p[arcel4同乙個包中的類能夠訪問pdestination,其他類都不能訪問pdestination。這意味著,如果客戶端程式員想要了解或者訪問這些成員,那是要受到限制的。甚至不能向下轉型成private內部類。於是private內部類給類的設計者提供了一種途徑,通過這種方式可以完全阻止任何依賴於型別的編碼,並且完全隱藏了實現的細節。此外,從客戶端程式員的角度來看,由於不能訪問任何新增加的、完全不屬於任何公共介面的方法,所以擴充套件介面是沒有價值的。
內部匿名類
public class parcel7 };}
public static void main(string args)
}contents()方法將返回值的生成和表示這個返回值的類定義結合在一起!但是這個類是匿名的,它沒有名字。看起來似乎是你正要建立乙個contents物件,但是,你卻說:「等一等,我想在這裡插入乙個類的定義」。
這種奇怪的語法指的是:建立乙個繼承自contents的匿名類的物件。通過new表示式返回的引用被自動向上轉型為對contents的引用。
如果定義乙個匿名內部類,並且希望它使用乙個在其外部定義的物件,那麼編譯器會要求其引數引用時final的。
如果想要做一些類似構造器的行為,怎麼辦呢?在匿名類中不可能有命名構造器(因為它根本沒有名字!),但通過例項初始化,就能夠達到為匿名內部類建立乙個構造器的效果。
public destination destination(final string dest, final float price)
public string readlabel() };}
使用內部匿名類達到工廠:
public class factories
inte***ce service
inte***ce servicefactory
class implementation1 implements service
public void method1()
public void method2()
public static servicefactory factory()};}
}class implementation2 implements service
public void method1()
public void method2()
public static servicefactory factory = new servicefactory() };}
巢狀類如果不需要內部類物件與其外部類物件之間有聯絡,那麼可以將內部類宣告為static。這通常被稱為巢狀類。想要理解static應用於內部類時的含義,就必須記住,普通的內部類物件隱式地儲存了乙個引用,指向建立它的外圍類物件。然而,當內部類是static的時,就不是這樣了。
巢狀類意味著:
1、要建立巢狀類的物件,並不需要其外圍類的物件
2、不能從巢狀類的物件中訪問非靜態的外圍類物件
巢狀類內部可以有靜態欄位和方法而普通內部類是不允許存在的
介面內部的類
正常情況下,不能在介面內部放置任何**,但巢狀類可以作為介面的一部分。你放到介面中的人都自動是public和static的。因為類是static的,只是將巢狀類置介面的命名空間內,這並不違反介面的規則。甚至可以在內部類中實現其外圍介面。
public inte***ce classinte***ce
public static void main(string args) }}
乙個內部類被巢狀多少層並不重要——它能透明地訪問所有它所嵌入的外圍類的所有成員。
為什麼需要內部類?
一般來說,內部類繼承自某個類或者實現某個介面,內部類的**操作建立它的外圍類的物件,所以可以認為內部類提供了某種進入其外圍類的視窗
內部類必須要會回答的乙個問題是:如果只是需要乙個對介面的引用,為什麼不通過外圍類實現那個介面呢?答案是:「如果這能滿足需求,那麼就應該這樣做」。那麼內部類實現乙個介面與外圍類實現這個介面有什麼區別呢?答案是:後者不能總享用到介面帶來的方便,有時候需要用到介面的實現。所以使用內部類最吸引人的原因是:
每乙個內部類都能獨立地繼承自乙個實現,所以無論外圍類是否已經繼承了某個實現,對於內部類都沒有影響。
如果沒有內部類提供的、可以繼承多個具體的或抽象的類的能力,一些設計與程式設計問題就很難解決,從這個角度上看,內部類使得多重繼承的解決方案變得完整。介面解決了部分問題,而內部類有效的實現了「多重繼承」。也就是說,內部類允許繼承多個非介面型別
閉包與**
閉包(closure)是乙個可呼叫的物件,它記錄了一些資訊,這些資訊來自於建立它的作用域。通過這個定義,可以看出內部類是物件導向的閉包,因為它不僅包含外圍類物件的資訊,還擁有乙個指向次外圍類物件的引用,在此作用域內,內部類有權操作所有的成員,包括private成員。
public class callbacks
}inte***ce incrementable
class callee1 implements incrementable
}class myincrement
static void f(myincrement mi)
}//加入你的類必須實現incrementable介面,你必須使用乙個內部類
class callee2 extends myincrement
private class closure implements incrementable
}incrementable getcallbackreference()
}
程式設計思想 內部類
1.內部類如何做到自動擁有對其外圍類所有成員的訪問權?當乙個外圍類建立乙個內部類物件時,此內部物件必定會秘密地捕獲乙個指向那個外圍類物件的引用。然後,當你訪問此外圍類的成員時,就是用那個引用來選擇外圍類的成員的。所以,你會發現 內部類的物件只能在其外部類物件相關的情況下被建立 內部類為非static...
Java程式設計思想 10內部類
內部類 定義在另外乙個類裡面的類 外部類 包含內部類的類 1 內部類可以直接訪問外部類的所有元素。因持有對外部類的引用 外部類類名.this 2 外部類訪問內部類,必須先建立內部類的物件 public class outer public static void main string args 前...
java程式設計思想筆記 內部類部分二
package com.wang.test public class test2 public static void main string args 以上是普通方式。如果內部類test3是乙個靜態類,則其與外圍類其實沒有任何關係,也不能訪問到外圍類的內部成員變數a。但是,如果是乙個靜態內部類,可...