Java的內部類
1、使用.this和.new
如果需要生成對外部類對象的引用,就可以使用外部類的名字後面緊跟著.this
public class Inn { void print() { System.out.print("Inn.print()"); } public class F1{ public Inn dothis(){ return Inn.this; } } public F1 f1() {return new F1();} public static void main(String[] args) { Inn inn= new Inn(); Inn.F1 f1 = inn.f1(); f1.dothis().print(); } }
一個Inn類中有一個print()方法,一個內部類F1,一個會返回F1對象的f1()方法,
F1類中有一個將返回Inn對象的dothis()方法。
main方法中先實例化一個Inn對象inn,然後調用Inn中的f1()方法生成一個F1的對象,f1.dothis就可以得到一個Inn對象並調用其中的輸出方法f().
上一個例子中,想要獲得一個內部類F1的對象,就必須先創建一個外部類Inn的對象,,這是因為內部類對象會暗暗的連接到外部類的對象上,除非定義的是靜態內部類。
然後同樣上一個例子中,想要獲得一個內部類F1的對象,除了必須要先創建一個外部類Inn的對象以為,還需要再調用Inn中的方法來獲得這個F1內部類對象。
public static void main(String[] args) { Inn inn = new Inn(); Inn.F1 f1 = new inn.F1();//這是錯的 f1.dothis().print(); }
這樣會編譯出錯,應該使用.new,
public static void main(String[] args) { Inn inn= new Inn(); Inn.F1 f1 = inn.new F1(); f1.dothis().print(); }
2、匿名內部類
在java中匿名內部類的創建需要實現抽象類或者接口所以得先創建一個抽象類或者接口
public class Inn { interface F { int i = 11; int value(); } public F f(){ return new F() { public int value() {return i;} }; }
public static void main(String[] args) { Inn inn = new Inn(); F f = inn.f(); System.out.println(f.value()); } }
這裏的Inn類中有一個F接口和一個f()方法,f()方法將返回值和這個返回值的生成和表示這個返回值的類的定義結合在一起了,然後這個類是沒有名字的。
這個語法是下面這個形式的簡化形式
public class Inn { interface F { int i = 11; int value(); } public class F1 implements F{ public int value() {return i;} } public F1 f() {return new F1();} public static void main(String[] args) { Inn inn = new Inn(); F f = inn.f(); System.out.println(f.value()); } }
這裏新建了一個F1的類,這個F1類就是剛剛的那個匿名的內部類,
帶參數的匿名內部類,這樣實現:
public class Inn { abstract class F { public F(int i) { } abstract int value(); } public F f(int i){ return new F(i) { public int value() {return i;} }; } public static void main(String[] args) { int i = 2; Inn inn = new Inn(); F f = inn.f(i); System.out.println(f.value()); } }
匿名抽象類由於沒有名字,所以它沒有構造函數,它的構造函數來自於它的父類也就是,因為接口是沒有構造器的所以要使用抽象類。
3、嵌套類
將內部類聲明為static的通常稱為嵌套類,普通的內部類對象隱式的保存了一個引用,指向創建它的外圍類對象,但是內部類是static的時候就是不是這樣的了,所以嵌套類意味著:
a、要創建嵌套類,將不需要其外圍類的對象
b、不能從嵌套類的對象中訪問非靜態的外圍類對象
c、普通內部類的字段與方法,自能放在類的外部層次上,所以普通內部類不能有static數據和static字段,也不能包含嵌套類,但是嵌套類能夠包含這些東西
d、嵌套類可以放在接口中作為接口的一部分,因為接口的任何類都是自動public和static 的,因為類是static的,只是將嵌套類置於接口的命名空間內而已,你甚至可以在內部類中實現外部接口。
4、如果創建了一個內部類,然後繼承其外圍類並重新定義此內部類的時候:
public class Inn { private F1 f; protected class F1{ public F1() { System.out.println("f1()"); } } public Inn() { System.out.println("Inn()"); f = new F1(); } } class F2 extends Inn{ public class F1{ public F1() { System.out.println("f2()"); } } public static void main(String[] args) { new F2(); } }
輸出結果為:
Inn()
f1()
這個例子說明,當繼承了某個外圍類的時候,內部類並沒有發生什麽神奇的變化,父類的內部類和子類的內部類是兩個完全獨立的實體,各自處在自己的命名空間內。
public class Inn { private F1 f; protected class F1{ public F1() { System.out.println("f1()"); } } public Inn() { System.out.println("Inn()"); f = new F1(); } } class F2 extends Inn{ public class F1{ public F1() { System.out.println("f2()"); } } public static void main(String[] args) { F2 test1 = new F2(); F2.F1 test2 = test1.new F1(); } }
這樣的輸出就是:
Inn()
f1()
f2()
如果想要明確的繼承內部類就需要這樣:
public class Inn { private F1 f; protected class F1{ public F1() { System.out.println("f1()"); } } public Inn() { System.out.println("Inn()"); f = new F1(); } } class F2 extends Inn{ public class F1 extends Inn.F1{ public F1() { System.out.println("f2()"); } } private F1 f; public F2() { System.out.println("F2()"); F1 f = new F1(); } public static void main(String[] args) { F2 test1 = new F2(); F2.F1 test2 = test1.new F1(); } }
輸出結果為:
Inn()
f1()
F2()
f1()
f2()
f1()
f2()
Java的內部類