转载自:https://my.oschina.net/nullObject/blog/181802?p=1


1
2
3
new ArrayList<String>(){{
add("");
}};

java 代码中出现这种写法,好奇add 函数是调用哪里的?

测试案例

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import java.util.*;
class Anonymous {
// 代码块 1
{
System.out.println("代码块:"+this.getClass().getName()); // 1】AnonymousDemo$1 //11】 aaa$1 //Anonymous
}
public Anonymous() {
System.out.println("无参构造函数:"+this.getClass().getName()); // 2】AnonymousDemo$1 // 12】aaa$1 //Anonymous
}
}
class aaa{
public aaa() {
Anonymous n = new Anonymous(){
// 代码块 4
{
System.out.println("Anonymous匿名类:"+this.getClass().getName()); // 13】 aaa$1
}
};
System.out.println("n:"+n.getClass().getName()); //14】 aaa$1
List<String> list_1 = new ArrayList<String>(){
{
System.out.println("List匿名类:"+this.getClass().getName()); // 15】aaa$2
}
};
System.out.println("list_1:"+list_1.getClass().getName()); // 16】 aaa$2
List<String> list_2 = new ArrayList<String>();
System.out.println("list_2:"+list_2.getClass().getName()); // 17】 java.util.ArrayList
}
}
class bbb {
public bbb() {
Anonymous n = new Anonymous();
System.out.println("n:"+n.getClass().getName()); // Anonymous
}
}
public class AnonymousDemo {
//@Test
public void test1() {
Anonymous n = new Anonymous(){
// 代码块 2
{
System.out.println("Anonymous匿名类:"+this.getClass().getName()); // 3】AnonymousDemo$1
}
};
System.out.println("n:"+n.getClass().getName()); // 4】AnonymousDemo$1
List<String> list_1 = new ArrayList<String>(){
@Override
public int size() {
System.out.println("size"); // 7】
return super.size(); // 8】
}
// 代码块3
{
System.out.println("List匿名类:"+this.getClass().getName()); // 5】AnonymousDemo$2
}
};
System.out.println("list_1:"+list_1.getClass().getName()); // 6】AnonymousDemo$2
System.out.println(list_1.size());
List<String> list_2 = new ArrayList<String>();
System.out.println("list_2:"+list_2.getClass().getName()); // 9】java.util.ArrayList
}
//@Test
public void test2(){
System.out.println("--------------------"); //10 】
aaa a = new aaa();
}
// @Test
public static void test3(){
System.out.println("--------------------");
bbb b = new bbb();
}
public static void main(String[] args) {
test1();
test2();
test3();
}
}

AnonymousDemo输出

代码块用法总结:

代码块写在那个类,就是那个类的匿名类;相当于匿名类继承原有类,并且覆盖方法。

执行数序:

1
2
3
4
5
6
7
8
9
父类的- 静态代码块 static {}
|- 普通代码块 {}
|- 构造函数
子类(匿名类)- 静态代码块 static {}
|- 普通代码块 {}
|- 构造函数
注意:一个 class 的静态代码块在 JVM 中只会调用一次。

根据 代码中注释 1】,2】… 可以证明上面的调用顺序是正确的。

代码分析

代码块写在那个类,就是那个类的匿名类;相当于匿名类继承原有类,并且覆盖方法。

分析下 4个代码块的写法

代码块1:给自定义 class Anonymous 添加代码块,会在构造函数之前被执行,并且每次创建Anonymous 对象都会执行。

代码块2:创建自定义 class Anonymous 对象时添加代码块,那就相当于 创建一个Anonymous class的匿名子类。所以在 匿名类、父类、以及所有的方法中显示的 ClassName 都是当前创建匿名类(AnonymousDemo)的子类(AnonymousDemo.$1); 可以结合 test3()对比。

代码块3:创建 系统 class ArrayList 对象时添加代码块,和代码块2的原理是一样的。这里也不会显示ArrayList的名字而是显示AnonymousDemo.$2;

代码块4: 和代码块2 完全一样