優點
內部類的類別
1、成員內部類是最普通的內部類,它的定義為位於另一個類的內部,可以無條件訪問外部類的所有成員屬性和成員方法(包括private成員和靜態成員)
注意:
當成員內部類擁有和外部類同名的成員變量或者方法時,會發生隱藏現象,即默認情況下訪問的是成員內部類的成員。如果要訪問外部類的同名成員,需要以下面的形式進行訪問:
外部類.this.成員變量 外部類.this.成員方法
在外部類中如果要訪問成員內部類的成員,必須先創建一個成員內部類的對象,再通過指向這個對象的引用來訪問
成員內部類是依附外部類而存在的,如果要創建成員內部類的對象,前提是必須存在一個外部類的對象。創建成員內部類對象的一般方式如下:
public class OuterClass { private double radius = 0; private InnerClass getInnerClassInstance() { return new InnerClass(); } class InnerClass { //內部類 public void drawSahpe() { System.out.println(radius); //外部類的private成員 } } public static void main(String[] args) { //第一種方式: OuterClass outter = new OuterClass(); OuterClass.InnerClass inner = outter.new InnerClass(); //必須通過Outter對象來創建 inner.drawSahpe(); //第二種方式: OuterClass.InnerClass inner1 = outter.getInnerClassInstance(); inner1.drawSahpe(); } }
內部類可以擁有private訪問權限、protected訪問權限、public訪問權限及包訪問權限。比如上面的例子,如果成員內部類Inner用private修飾,則只能在外部類的內部訪問,如果用public修飾,則任何地方都能訪問;如果用protected修飾,則只能在同一個包下或者繼承外部類的情況下訪問;
2、方法內部類(局部內部類)是定義在一個方法或者一個作用域里面的類,它和成員內部類的區別在於局部內部類的訪問僅限於方法內或者該作用域內。
非靜態方法里的內部類、匿名內部類
1)、非靜態方法的內部類可以訪問外部類的實例變量、靜態變量
2)、非靜態方法的內部類可以訪問方法的final變量
靜態方法里的內部類、匿名內部類
1)、靜態方法的內部類可以訪問外部類的靜態變量,但無法訪問實例的外部變量
2)、靜態方法的內部類可以訪問方法的final變量,但無法訪問方法的非final的變量
注意局部內部類就像是方法里面的一個局部變量一樣,是不能有public、protected、private以及static修飾符的。
3、匿名內部類
一般使用匿名內部類的方法來編寫事件監聽代碼。同樣的,匿名內部類也是不能有訪問修飾符和static修飾符的;
匿名內部類是唯一一種沒有構造器的類。正因為其沒有構造器,所以匿名內部類的使用范圍非常有限,大部分匿名內部類用於接口回調。匿名內部類在編譯的時候由系統自動起名為Outter$1.class。一般來說,匿名內部類用於繼承其他類或是實現接口,並不需要增加額外的方法,只是對繼承方法的實現或是重寫。
public class Button { public void click(){ //匿名內部類,實現的是ActionListener接口 new ActionListener(){ public void onAction(){ System.out.println("click action..."); } }.onAction(); } //匿名內部類必須繼承或實現一個已有的接口 public interface ActionListener{ public void onAction(); } public static void main(String[] args) { Button button=new Button(); button.click(); } }
4、靜態內部類
靜態內部類也是定義在另一個類里面的類,只不過在類的前面多了一個關鍵字static。
靜態內部類是不需要依賴於外部類的,這點和類的靜態成員屬性有點類似,並且它不能使用外部類的非static成員變量或者方法,因為在沒有外部類的對象的情況下,可以創建靜態內部類的對象,如果允許訪問外部類的非static成員就會產生矛盾,因為外部類的非static成員必須依附於具體的對象。
public class OuterClass { private double radius = 0; static class InnerClass { //靜態內部類 public void drawSahpe() { //System.out.println(radius); //不能訪問外部類的非靜態成員 } } public static void main(String[] args) { OuterClass.InnerClass inner = new OuterClass.InnerClass(); } }
內部類可以直接訪問外部類元素,但是外部類不可以直接訪問內部類的元素
public class OuterClass { private String outerName; public class InnerClass{ private int innerName; InnerClass(){ //內部類可以訪問外部類的元素 outerName="outer class"; } public void display(){ System.out.println(outerName); } } public static void main(String[] args) { OuterClass outerClass = new OuterClass(); OuterClass.InnerClass innerClass = outerClass.new InnerClass(); innerClass.display();
//outerClass.innerName; //報錯,外部類不能直接訪問內部類的元素 } }
內部類可以直接訪問外部類屬性,盡管外部類屬性是用private修飾的。在創建外部類時,內部類會自動捕獲一個外部類的引用,所以內部類訪問外部類元素,實際上是通過他所持有外部類引用訪問的。
內部類和外部類的聯系
內部類是一個編譯時概念,編譯后外部類及其內部類會生成兩個獨立的class文件,內部類是一個相對獨立的實體,與外部類不是is a的關系
外部類如何訪問內部類元素?
public class OuterClass { public void display(){ //外部類訪問內部類元素,需要通過內部類引用間接訪問 InnerClass innerClass=new InnerClass(); innerClass.innerDisplay(); } public class InnerClass{ public void innerDisplay(){ System.out.println("I am inner class"); } } public static void main(String[] args) { OuterClass outerClass=new OuterClass(); outerClass.display(); } }
關於成員內部類的繼承問題。一般來說,內部類是很少用來作為繼承用的。但是當用來繼承的話,要注意兩點:
1)成員內部類的引用方式必須為 Outter.Inner.
2)構造器中必須有指向外部類對象的引用,並通過這個引用調用super()。
class WithInner { class Inner{ } } class InheritInner extends WithInner.Inner { // InheritInner() 是不能通過編譯的,一定要加上形參 InheritInner(WithInner wi) { wi.super(); //必須有這句調用 } public static void main(String[] args) { WithInner wi = new WithInner(); InheritInner obj = new InheritInner(wi); } }
參考資料:
《java編程思想》
http://www.cnblogs.com/dolphin0520/