相關閱讀:java
JAVA基礎(二)內存優化-使用Java引用作緩存
JAVA基礎(三)ClassLoader實現熱加載
JAVA基礎(四)枚舉(enum)和常量定義,工廠類使用對比
JAVA基礎(五)函數式接口-複用,解耦之利刃
JAVA編程思想(一)經過依賴注入增長擴展性
JAVA編程思想(二)如何面向接口編程
JAVA編程思想(三)去掉彆扭的if,自注冊策略模式優雅知足開閉原則
JAVA編程思想(四)Builder模式經典範式以及和工廠模式如何選?
HikariPool源碼(二)設計思想借鑑
人在職場(一)IT大廠生存法則編程
首先Java類的做用是功能內聚,將相近特性的功能內聚到一個類中,例如StringUtil類內聚String相關的功能,DateUtil類內聚Date相關的功能,那麼內部類天然也有功能內聚的做用,與通常類不一樣的是,定義一個內部類一般意味者既要功能內聚,又要對外屏蔽可見性,即不但願外部可見,減小對外暴露的接口,這樣從源碼結構上來看,須要瞭解的類信息更少,更簡潔。緩存
既然內部類是爲了對外屏蔽可見性,那麼內部類的功能不能直接用內部方法實現麼?函數
內部類能夠經過內部方法實現,但有的場景更適合用內部類來實現:
1.有一組相近的功能,能夠內聚,歸屬到一個特性,若是都用方法實現,那麼原來這個類的方法會不少。
2.須要繼承或者實現某個接口,此時經過方法就沒法作到。post
從static關鍵字的通常用法出發很容易理解二者的區別:
1.static方法不能訪問非static成員,同理靜態內部類也同樣。
2.非static方法能訪問非static成員,同理內部類也同樣。
3.非靜態成員,須要經過類實例去訪問,同理訪問內部類也同樣。
4.靜態成員,能夠經過類而非類實例來訪問,同理訪問靜態內部類也同樣。
所以,只要記住static關鍵字在通常類中的用法則可。下面看一個例子:優化
public class OuterClass {
private String outerField; // 非靜態成員
private static String staticOuterField; // 靜態成員
public InnerClass innerClass = new InnerClass();
public StaticInterClass staticInterClass = new StaticInterClass();
public class InnerClass {
public void printFields() {
System.out.println(outerField); // 可訪問非靜態成員
System.out.println(staticOuterField); // 可訪問靜態成員
}
}
public static class StaticInterClass {
public void printFields() {
System.out.println(outerField); // 報錯,不可訪問非靜態成員
System.out.println(staticOuterField); // 可訪問靜態成員
}
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
// 類的訪問有區別
OuterClass.StaticInterClass staticInterClass = new OuterClass.StaticInterClass(); // 靜態內部類能夠直接經過類來訪問
OuterClass.InnerClass in = new OuterClass.InnerClass(); // 報錯,內部類不能經過類去訪問
// 類實例的訪問是同樣的
outerClass.innerClass.printFields();
outerClass.staticInterClass.printFields();
}
}
複製代碼
這個也能夠結合static關鍵字的通常用法出發來考慮:
1.外部其餘類須要如何訪問內部類? 例如是經過外部類的實例訪問,仍是經過外部類訪問。若是經過類訪問,那麼就使用靜態內部類,不然使用內部類。
2.是否須要訪問類的非靜態成員,若是須要就用內部類,不然用靜態內部類。ui
在Java中不支持繼承多個類,可是在一個類中能夠定義多個內部類,不一樣的內部類又能夠繼承不一樣的類,這樣就等於同一個類能夠繼承多個類。不過這樣作跟使用組合也差很少了,都是在內部持有了一個新的類,而繼承和組合的區別是繼承能夠繼承一個抽象類,而組合不能。咱們來看一個例子:spa
public class FlyingDog extends Dog {
// Bird bird = new Bird(); 這麼用是組合
InnerBird innerBird = new InnerBird(); // 這麼用是繼承
public void fly() {
// bird.fly(); 這麼用是組合
innerBird.fly(); // 這麼用是繼承
}
// 實現了多重繼承,不過就這個例子而言,使用多重繼承跟使用組合沒有啥區別。惟一區別是僅當父類是抽象類的時候只能使用繼承。
private class InnerBird extends Bird {
}
public static void main(String[] args) {
FlyingDog flyingDog = new FlyingDog();
flyingDog.fly();
flyingDog.run();
}
}
class Bird {
public void fly() {
System.out.println("I can fly");
}
}
class Dog {
public void run() {
System.out.println("I can run");
}
}
複製代碼
end.設計