先看看下面的代码能不能编译通过:
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。