
一個(gè)類的定義放在另一個(gè)定義內(nèi)部,這就是內(nèi)部類。
10.1 創(chuàng)建內(nèi)部類
public class Parcel1{
class Contents{
private int i = 11;
public int value (){ return i; }
}
class Destination {
private String able;
Destinaltion(String whereTo){
label = whereTo;
}
String readLabel (){ return label;}
}
public void ship(String dest){
Contents c = new Contents();
Destination d = new Destination(dest);
System.out.println(d.readLabel);
}
public static void main(String[] args){
Parcel1 p = new Parcel1();
p.ship("Tasmainaaaaa");
}
}
10.2 鏈接到外部類
內(nèi)部類是一種名字隱藏和組織代碼的模式,當(dāng)生成內(nèi)部類對(duì)象時(shí),此對(duì)象可以用訪問(wèn)外圍對(duì)象的所有成員
10.3 使用 .this與。new
對(duì)外部類的引用:外部類的名字緊跟this.
創(chuàng)建內(nèi)部類對(duì)象:使用 .new語(yǔ)法
10.4 內(nèi)部類與向上轉(zhuǎn)型
內(nèi)部類向上轉(zhuǎn)型為基類或一個(gè)接口,所得到的是指向基類或接口的引用,隱藏實(shí)現(xiàn)細(xì)節(jié)
public interface Destination{
String readLabel();
}
public interface Contents{
int value();
}
//(接口的所有成員自動(dòng)被設(shè)置成public)
class Parcel4{
private class Pcontents implements Contenets {
private int i =1;
public int value(){return i;}
}
protected class PDestination implements Destination{
private String label;
private PDestination(String whereTo){ label = whereTo;}
public String readLabel(){return label;}
}
public Destination destination(String s){
return new PDestinations(s);
}
public Contents contents(){
return new PContents();
}
}
public class TestPracel{
public static void main(String[] args){
Pracel4 p = new Parcel4();
Contents c = p.contents();
Destriation d = p.destination("tasmainaaa");
}
內(nèi)部類PContents是privae,只有Parcel4 可以訪問(wèn), PDesination是protected只有Parcel4及子類可以訪問(wèn)
private內(nèi)部類可以阻止任何依賴型的代碼,隱藏實(shí)現(xiàn)細(xì)節(jié)。
10.5 在方法和作用域內(nèi)的內(nèi)部類
可以在方法或在作用域定義內(nèi)部類。
理由
- 1 實(shí)現(xiàn)某種類型的接口,可以創(chuàng)建并返回對(duì)其引用。
- 2 創(chuàng)建一個(gè)類來(lái)輔助解決方案,但不希望這個(gè)類時(shí)公用的。
內(nèi)部類的實(shí)現(xiàn)。
- 1> 定義在方法中的內(nèi)部類
- 2>定義在作用域內(nèi)的類,作用域的方法在內(nèi)部
- 3>一個(gè)實(shí)現(xiàn)接口的匿名類
- 4>一個(gè)匿名類,它擴(kuò)展了默認(rèn)構(gòu)造器的類
- 5>一個(gè)匿名類,它執(zhí)行字段初始化
- 6>一個(gè)匿名類,它通過(guò)實(shí)例初始化實(shí)現(xiàn)構(gòu)造(匿名類不可能有構(gòu)造器)
10.6 匿名內(nèi)部類
public class Parcel7{
public Contents contents(){
return new Contents(){
private int i =11;
public int value(){return i;}
};
}
public static void main(String[] args){
Parcel7 p = new Parcel7();
Contents c = p.contents();
}
}
匿名內(nèi)部類末尾的分號(hào),并不是用來(lái)標(biāo)記內(nèi)部類的結(jié)束,標(biāo)記的是表達(dá)式的結(jié)束,這個(gè)表達(dá)式包含了匿名內(nèi)部類。
匿名內(nèi)部類使用外部對(duì)象(不包含基類使用)參數(shù)引用需要final修飾。
匿名內(nèi)部類實(shí)例初始化的效果就是構(gòu)造器,但受到了限制(不能重載實(shí)例初始化方法,匿名內(nèi)部類可以擴(kuò)展類,也可以實(shí)現(xiàn)接口,但不能兩者兼?zhèn)?,如果是?shí)現(xiàn)接口也只能實(shí)現(xiàn)一個(gè)接口)
- 10.6.1 再訪工廠方法
interface Service{
void method1();
void method2();
}
interface ServiceFactory{
Service getService();
}
class Implementation1 implement Service{
private Implementation1(){}
public method1(){ print("Implementation1 method1")}
public method2(){ print("Implementation1 method2")}
}
public static ServiceFactory factory =
new ServiceFactory(){
public Service getService(){
return new Implementation1 ();
};
}
class Implementation2 implement Service{
private Implementation2(){}
public method1(){ print("Implementation2 method1")}
public method2(){ print("Implementation2 method2")}
}
public static ServiceFactory factory =
new ServiceFactory(){
public Service getService(){
return new Implementation2 ();
};
}
public class Factories{
public static void ServiceConsumer(ServiceFactory factory){
Service s = factory.getService();
s.method1();
s.method2();
}
public static void main(String[] args){
ServiceConsumer(Implementation1.factory);
ServiceConsumer(Implementation2.factory);
}
}
由上構(gòu)造器都可以是private,并沒(méi)有創(chuàng)建工廠的類具名
優(yōu)先使用類而不是接口。如果你的設(shè)計(jì)需要接口,你必須了解它。否則,不到迫不得已,不需要將它放到你的設(shè)計(jì)中
10.7 嵌套類
如果不需要內(nèi)部類對(duì)象與外圍類有聯(lián)系,可以將內(nèi)部類對(duì)象聲明為static,這就是嵌套類。
普通內(nèi)部類對(duì)象隱式保存了一個(gè)引用,指向創(chuàng)建它的外圍類對(duì)象,而內(nèi)部類是static時(shí),嵌套類就意味著
- 1 要?jiǎng)?chuàng)建嵌套類的對(duì)象,并不需要外圍類對(duì)象。
- 2 不能從嵌套類對(duì)象中訪問(wèn)費(fèi)靜態(tài)的外圍類對(duì)象
(注意普通類內(nèi)部不能有static數(shù)據(jù)和static字段,也不能包含嵌套類,但嵌套類可以包含這些東西)
10.8 為什么需要內(nèi)部類
Sun公司為什么會(huì)增加這個(gè)語(yǔ)言特性,一般來(lái)說(shuō),內(nèi)部類繼承某個(gè)類或?qū)崿F(xiàn)某個(gè)接口,內(nèi)部類的代碼操作創(chuàng)建它的外圍類的對(duì)象,內(nèi)部類提供了某種進(jìn)入外圍類的窗口。
- 1) 如果只是需要一個(gè)接口的引用,為什么不通過(guò)外圍類實(shí)現(xiàn)那個(gè)接口
答案是:“如果這能滿足需求,那么就應(yīng)該這樣做” - 2) 內(nèi)部類實(shí)現(xiàn)一個(gè)接口與外圍類實(shí)現(xiàn)這個(gè)接口有什么區(qū)別
答案是:后者不是總能享用到接口帶來(lái)的方便,有時(shí)需要用到接口的實(shí)現(xiàn),所以使用最吸引人的原因是:
每個(gè)內(nèi)部類都能獨(dú)立繼承一個(gè)接口的實(shí)現(xiàn),所以無(wú)論外圍類是否已經(jīng)繼承了某個(gè)接口的實(shí)現(xiàn),對(duì)于內(nèi)部類都沒(méi)有影響
也就是說(shuō)內(nèi)部類允許繼承多個(gè)非接口類型
內(nèi)部類可以獲得其他一些特性
1)內(nèi)部類可以有多個(gè)實(shí)例,每個(gè)實(shí)例都有自己的狀態(tài)信息,并且與外圍類的對(duì)象信息相互獨(dú)立。
2)在單個(gè)外圍類中,可以讓內(nèi)部類以不同的方式實(shí)現(xiàn)同一個(gè)接口,或繼承同一個(gè)類。
3)創(chuàng)建內(nèi)部類對(duì)象不依賴外圍類對(duì)象的創(chuàng)建。
4)內(nèi)部類沒(méi)有“is-a”關(guān)系,他就是一個(gè)獨(dú)立的類
10.8.1 閉包與回調(diào)
通過(guò)內(nèi)部類提供的閉包功能是優(yōu)良的解決方案,它比指針更靈活,更安全。
10.9 內(nèi)部類的繼承
內(nèi)部類的構(gòu)造器不需連接到指向外圍類對(duì)象的引用,所以在繼承內(nèi)部類的時(shí)候,事情會(huì)變得有點(diǎn)復(fù)雜,問(wèn)題在于,那個(gè)指向外圍類的對(duì)象的“秘密的”引用必須被初始化,而在導(dǎo)出類中不再存在可連接的默認(rèn)對(duì)象。要解決這個(gè)問(wèn)題,必須使用特殊的語(yǔ)法說(shuō)明它們之間的關(guān)聯(lián)。
class WithInner{
class Inner{}
}
public class InheritInner extends WithInner.Inner{
InheritInner(WithInner wi){}
wi.super();
}
public static void main(String[] args){
WithInner wi = new WitnInner();
InherItInner ii = new InheritInner(wi);
}
}
10.10 內(nèi)部類可以被覆蓋嗎
覆蓋內(nèi)部類就好像是它的一個(gè)方法,其實(shí)并不起什么作用
10.11 局部?jī)?nèi)部類
可以訪問(wèn)當(dāng)前代碼塊內(nèi)的常量,以及此外圍類所有成員。
匿名內(nèi)部類和局部?jī)?nèi)部類創(chuàng)建的比較
interface Counter{
int next();
}
public class LocalInnerClass{
private int count = 0;
Counter getCounter(final String name){
class LocalCounter implements Counter{
public LocalCounter(){}
public int next(){
return count++;
}
}
}
Counter getCounter2(final String name){
return new Counter(){
public int next(){
return count++;
}
};
}
}
當(dāng)需要一個(gè)已命名的構(gòu)造器,或者需要重載構(gòu)造器,使用局部?jī)?nèi)部類,匿名內(nèi)部類只能用于實(shí)例初始化。
當(dāng)需要不止一個(gè)內(nèi)部類對(duì)象時(shí),使用局部?jī)?nèi)部類。
10.12 內(nèi)部類標(biāo)識(shí)符
每個(gè)類都會(huì)產(chǎn)生一個(gè).class文件,其中包含了如何創(chuàng)建該類型的全部信息(此信息產(chǎn)生一個(gè)“meta-class”,叫Class對(duì)象)內(nèi)部類必須生成一個(gè).class文件以包含它們的Class對(duì)象信息。這些文件的命名有嚴(yán)格的規(guī)定:外圍類的名字,加上“$”再加上內(nèi)部類的名字