double-brace initialization
今日看大佬代码,发现大佬是这样初始化ArrayList数组的。
public static void main(String args[]) {
List<Animal> arrayList = new ArrayList<Animal>() {{
add(new Animal() {{
setColor("yellow");
setName("godA");
}});
}};
System.out.println(arrayList);
}
@Data
class Animal{
private String color;
private String name;
}
代码中多次使用了双括号{{ ... }}这种初始化对象的方式,上网搜索了一下这种方法叫做double-brace initialization。
这里的第一层括号与匿名内部类相关,下面就先巩固回忆一下匿名内部类的使用方式。
匿名内部类简介
Java中的嵌套类是在掌握匿名内类之前所需要的先决条件。它是一个没有名字的内类,只为其创建一个对象。当创建一个具有某些 "额外功能 "的对象实例时,匿名内类是非常有用的,例如覆盖一个类或接口的方法,而不需要实际对一个类进行子类化。
语法
匿名类表达式的语法与构造函数的调用一样,只是在一个代码块中包含了一个类的定义。
Test t = new Test()
{
// 属性或者方法
private String name;
// 可以覆盖某一个方法
public void test_method()
{
........
........
}
};
这里的Test既可以是一个类,也可以是一个接口,也可以是一个抽象类。
一个普通的类可以实现任意数量的接口,但匿名的内层类一次只能实现一个接口。
一个普通的类可以扩展一个类并同时实现任意数量的接口。但是匿名内层类可以扩展一个类,也可以实现一个接口,但不能同时实现。
对于普通/正常类,我们可以编写任意数量的构造函数,但我们不能为匿名内层类编写任何构造函数,因为匿名类没有任何名字。
访问范围
像局部类一样,匿名类可以捕获变量;它们对包围范围的局部变量也有同样的访问权。
一个匿名类可以访问其包围类的成员。
一个匿名类不能访问其包围作用域中未被声明为final或有效final的局部变量。
像嵌套类一样,在匿名类中对一个类型(如变量)的声明会影射包围作用域中具有相同名称的任何其他声明。
在成员方面,匿名类也有与局部类相同的限制。
我们不能在匿名类中声明静态初始化器或成员接口。
一个匿名类可以有静态成员,只要它们是常量变量。
匿名内部类类型
匿名类可以分为两种类型:继承类型匿名类,接口类型匿名类,
继承类型匿名类
// Java program to illustrate creating an immediate thread
// Using Anonymous Inner class that extends a Class
// Main class
class MyThread {
// Main driver method
public static void main(String[] args)
{
// Using Anonymous Inner class that extends a class
// Here a Thread class
Thread t = new Thread() {
// run() method for the thread
public void run()
{
// Print statement for child thread
// execution
System.out.println("Child Thread");
}
};
// Starting the thread
t.start();
// Displaying main thread only for readability
System.out.println("Main Thread");
}
}
接口类型匿名类
// Java program to illustrate defining a thread
// Using Anonymous Inner class that implements an interface
// Main class
class MyThread {
// Main driver method
public static void main(String[] args)
{
// Here we are using Anonymous Inner class
// that implements a interface i.e. Here Runnable
// interface
Runnable r = new Runnable() {
// run() method for the thread
public void run()
{
// Print statement when run() is invoked
System.out.println("Child Thread");
}
};
// Creating thread in main() using Thread class
Thread t = new Thread(r);
// Starting the thread using start() method
// which invokes run() method automatically
t.start();
// Print statement only
System.out.println("Main Thread");
}
}
匿名类常见使用方法
// Java program to illustrate defining a thread
// Using Anonymous Inner class that define inside argument
// Main class
class MyThread {
// Main driver method
public static void main(String[] args)
{
// Using Anonymous Inner class that define inside
// argument
// Here constructor argument
Thread t = new Thread(new Runnable() {
public void run()
{
System.out.println("Child Thread");
}
});
t.start();
System.out.println("Main Thread");
}
}
double-brace与匿名类的结合
复习完匿名内部类,我们在回过头看double-brace initialization。
双括号初始化中的第一个括号是用来创建一个匿名内类的。我们已经用这样的方式做了很多匿名的内类。第二个大括号是它与Java中普通大括号的不同之处。
第二个大括号是初始化块,它与声明的匿名内类一起使用,可以直接操作匿名内部类的方法和属性,例如下面的代码里,继承ArrayList所有方法的匿名内部类调用了自己的add方法。
public static void main(String args[]) {
List<Animal> arrayList = new ArrayList<Animal>() {{
add(new Animal() {{
setColor("yellow");
setName("godA");
}});
}};
System.out.println(arrayList);
}
@Data
class Animal{
private String color;
private String name;
}
1113

被折叠的 条评论
为什么被折叠?



