標籤:
http://www.cnblogs.com/wenruo/p/5387995.html
內部類 就是在類中嵌套的另一個類。
非靜態內部類
建立內部類的方式就是把類定義在外部類裡面。
class Out { class In { } }
內部類對於外部類是特殊的,內部類可以訪問到外部類的所有成員,包括私人成員。
class Outer { private String str = "Outer"; class Inner { public Inner() {str = "Inner";} }}
當產生一個內部類對象的時候,它自動和它的外部類有聯絡,所以要建立內部類對象,必須先有外部類對象。
內部類的類型在外部類除外部類靜態方法外不能直接使用內部類的名字,應為OuterClassName.InnerClassName。
內部類可以為私人許可權,當內部類為私人時,外部類外對內部類是不可見的。內部類不能有static的域,除非是final的。
建立內部類的方法:
1,外部類方法發返回內部類的引用。
2,通過.new文法實現。
class Outer { class Inner { } public Inner getInner() { return new Inner(); }}public class Test { public static void main(String args) { Outer out = new Outer(); Outer.Inner in = out.new Inner(); Outer.Inner in1 = out.getInner(); }}
在內部類通過OuterClassName.this可以訪問外部類對象。
class Outer { int a = 17; class Inner { int a = 3; public void f() { System.out.println(this.a + " " + Outer.this.a); } }}public class Test { public static void main(String[] args) { Outer out = new Outer(); Outer.Inner in = out.new Inner(); in.f(); }} // output:3 17
類也可以定義在方法內部。這樣類的範圍也就限制在方法內部。【名字實在是很糟糕
interface Inf { void f();}class Outer { public Inf f() { class Inner implements Inf { public void f() { System.out.println("Inner"); } } return new Inner(); }}public class Test{ public static void main(String[] args) { Outer out = new Outer(); Inf inf = out.f(); inf.f(); }}
在這個例子中,通過向上轉型為介面類型,完全隱藏了具體實現。
匿名內部類
匿名內部類就是沒有名字的內部類使用範例
interface Contents { int value();}public class AnonymousInnerClassTest { public Contents contents() { return new Contents() { private int i = 11; public int value() { return i; } }; } public static void main(String[] args) { AnonymousInnerClassTest a = new AnonymousInnerClassTest(); Contents c = a.contents(); System.out.println(c.value()); }}
乍一看很奇怪,但其實很方便的使用方法。在需要使用類的地方直接寫一個類的定義。
很容易想到因為匿名類沒有名字,而構造器的名字需要和類名一樣,所以……它沒!有!構!造!器!
如果基類需要有參數的構造器怎麼辦?只需要在new的時候加上參數就可以了。
public class A { int i, j; A(int i, int j) { this.i = i; this.j = j; }}class B { public A f(int i, int j) { return new A(i, j) { //... }; }}
那麼如果一個匿名內部類需要構造器來初始化的時候怎麼辦呢?
在學習類的初始化順序的時候知道,在構建類對象時是先執行非靜態程式碼片段再執行構造器。所以這裡可以用代碼塊帶到類似構造器的效果。
class B { public void print() {}}public class A { public B getB() { return new B() { { System.out.println("Inside Instance initialize."); } public void print() { System.out.println("in anonymous f()"); } }; } public static void main(String[] args) { B b = new A().getB(); b.print(); }}
如果定義一個匿名內部類,並且希望它使用一個在其外部定義的外部對象,那麼編譯器會要求其參數引用是final的。
Java8中,可以不是final了,但是預設是final的,在內部類不能改變。原因是在內部類,外部變數相當於形參,也就是在內部類改變對外部類無影響,就會造成資料不同步的問題。
interface I {}public class A { public static void main(String[] args) { int x = 0; new I() { // x = 3; error void f() { System.out.println(x); } }; }}
Java8中匿名內部類可以用lambda運算式代替,感覺超簡潔。文法糖,寫代碼方便,不過也增加了閱讀代碼的難度。
interface A1 { void print(); }class A2 { public A1 f() { return () -> { System.out.println("lambda expression."); }; }}public class Test { public static void main(String[] args) { A1 a1 = new A2().f(); a1.print(); }}
略過略過,以後再學,,,
靜態內部類
靜態內部類常被稱作嵌套類。
建立靜態內部類的對象,並不需要外部類的對象。
不能從嵌套類的對象中訪問非靜態外圍類對象。
普通的內部類不能有static資料和static欄位,也不能包含嵌套類,但是嵌套類可以包含所有這些東西。
class B { static class C { }}public class A { public static void main(String[] args) { B.C c = new B.C(); }}
待續。。。
java 內部類的使用