先看看下面的代碼能不能編譯通過:
1
2
3
4
5
6
7
8
|
public static void main(String[] args) { List l1 = new ArrayList(); List l2 = new ArrayList(){}; List l3 = new ArrayList(){{}}; System.out.println(l1.getClass() == l2.getClass() ); System.out.println(l2.getClass() == l3.getClass() ); System.out.println(l1.getClass() == l3.getClass() ); } |
答案是能通過編譯,輸出3個false。l1很容易理解,就是聲明了一個
ArrayList對象,那么l2、l3是什么呢?
l2是一個匿名類內部類對象,繼承ArrayList;
l3語句有些古怪,帶了兩個大括號,其實我們這樣寫就會明白了,這也是一個匿名內部類的定義,它的代碼類似如下:
1
2
3
4
5
6
|
class Sub extends ArrayList { { //初始化代碼塊 } } List l3 = new Sub(); |
看到了吧,就是多了一個初始化代碼塊而已,起到構造函數的功能。當然一個類中的構造代碼塊可以有多個,下面的代碼是可以編譯的:
List l4 = new ArrayList(){{}{}{}};
匿名內部類雖然可以用一個初始化代碼塊來充當構造函數,但其構造函數還是進行了特殊的處理,它在初始化時直接調用父類的同參構造函數,然后在調用自己的代碼塊,例如:
1
2
3
4
5
|
List l5 = new ArrayList( 5 ){ { System.out.println( "我是匿名內部類" ); } }; |
等價于:
1
2
3
4
5
6
7
8
9
|
class Sub extends ArrayList{ { System.out.println( "我是匿名內部類" ); } Sub( int num){ super (num); } } List l5 = new Sub( 5 ); |
我們來看段示例代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package testtest; public class Main { public static void main(String[] args) { InnerTest inner = new InnerTest(); Test t = inner.get( 3 ); System.out.println(t.getI()); } } class Test { private int i; public Test( int i) { this .i = i; } public int getI() { return i; } } class InnerTest { public Test get( int x) { return new Test(x) { @Override public int getI() { return super .getI() * 10 ; } }; } } |
編譯之后得到4個class文件:Test.class,InnerTest.class,InnerTest$1.class以及Main.class。容易看出來,Main.class是測試類的class文件,Test.class是超類Test的class文件,InnerTest.class是InnerTest 的class文件,最值得關注的就是匿名內部類的class文件InnerTest$1.class。