例如一個類cow,它須要組合一個cowLeg類,cowLeg類只有在cow裏纔有意義,離開cow沒有任何意義。因此咱們能夠把cowLeg定義爲cow的一個內部類。java
做用:安全
①更好的封裝。內部類類除了public和包之外,還可以使用private,protected,static修飾符,所以能夠提供更好的安全性。spa
②內部類成員能夠直接訪問外部類的私有數據。外部類不能訪問內部類的實現細節,例如內部類的成員變量。code
③匿名內部類適合用於建立那些僅須要使用一次的類,如「接口」中的addCommand類和printCommand類均可定義爲匿名內部類。對象
注意:非靜態內部類不能擁有靜態成員。繼承
內部類的分類:接口
1.非靜態內部類:get
非靜態內部類訪問某個變量時的順序①查找該方法內的局部變量②在該方法所在的內部類中查找成員變量③在外部類中查找④編譯報錯編譯
非靜態內部類的成員只在非靜態內部類範圍內是可知的,並不能被外部類直接使用。若是外部類須要訪問非靜態內部類的成員,必須顯式建立非靜態內部類對象來調用訪問其實例變量。class
java不容許在非靜態內部類裏定義靜態成員。
2.靜態內部類:
static修飾內部類,則這個內部類就屬於類自己,(而不屬於某個對象)。
靜態內部類能夠包含靜態成員,也能夠包含非靜態成員。
根據靜態成員不能訪問非靜態成員的原則,靜態內部類不能訪問外部類的實例成員。(即便是靜態內部類的實例方法也不能訪問外部類的實例成員)。
外部類依然不能直接訪問靜態內部類的成員,可是能夠經過靜態內部類的類名做爲調用者來訪問靜態內部類的類成員。
java容許接口中定義內部類,可是必須(默認也是)是public static 修飾。即接口內部類施能是靜態內部類。
3.使用內部類:
外部類之外使用非靜態內部類:
在外部類之外使用內部類,內部類完整的類名應該是OuterClass.InnerClass
聲明建立一個非靜態內部類:
Out.In in=new Out().new IN();
等號左邊爲in的完整類名的聲明,右邊體現了用外部類的對象來建立內部類對象!
外部類之外使用靜態內部類:
StaticOut.staticIn in=new StaticOut.StaticIn();
和上面比較可知,左側和上面相同,右側用外部類的類名來建立內部類對象!、
4.局部內部類:(不多用)
若是把一個內部類放在方法裏定義,則這個內部類就是一個局部內部類。
5.匿名內部類:
匿名內部類適合建立只須要一次使用的類。例如命令模式中的Command對象。
規則:①匿名內部類不能使抽象類。(由於在建立匿名內部類的時,會當即建立它的對象)
②匿名內部類不能定義構造器。(匿名內部類沒有類名,不能定義構造器,可使用初始化塊)
最經常使用的建立匿名內部類的方式是須要建立某個接口類型的對象。(即實現該接口的類的對象)
interface product{ public double getPrice(); public String getName(); } public class AnonymousTest { public void test(product p) { System.out.println("購買了一個"+p.getName()+",花掉了"+p.getPrice()); } public static void main(String [] args) { AnonymousTest ta=new AnonymousTest(); //調用test方法時,須要傳入一個product //此處傳入其匿名實現類的實例 ta.test(new product() { public double getPrice() { return 567.8; } public String getName() { return "agp顯卡"; } }); } }
也能夠經過繼承父類(包括抽象類)來建立匿名內部類,匿名內部類將擁有和父類類似的構造器,此處相思知的就是擁有相同的形參列表。
匿名內部類:能夠選擇父類的構造器,而後在類的內部能夠寫初始化塊,實現抽象方法,重寫父類的實例方法。
局部變量和匿名內部類訪問的局部變量必須被final修飾(默認也是)。