Java new对象时直接在后面加两个{{是什么用法?
例如以下代码片段(取自Mybatis):
public static String buildGetUsersByName(
final String name, final String orderByColumn) {
return new SQL(){{
SELECT("*");
FROM("users");
WHERE("name like #{name} || '%'");
ORDER_BY(orderByColumn);
}}.toString();
}
下面是一个简单的例子,应该能更容易理解一点,按照你的写法放到了main方法中。
public class Test {
public static void main(String[] args) throws Exception {
List<String> list = new ArrayList<String>() {
{
add("a");
add("b");
}
};
}
}
然后我们把编译过后的class文件拿出来看看,究竟发生了什么。首先看到的是,一个Test.java编译出了2个class
isaac-mbp:basic foxty$ ls -l
total 16
-rw-r--r-- 1 foxty staff 542 2 9 22:08 Test$1.class
-rw-r--r-- 1 foxty staff 629 2 9 22:08 Test.class
接着我们看看本身的Test.class被编译成了什么,直接用jdk自带的javap就行。
isaac-mbp:basic foxty$ javap -c Test.class
Compiled from "Test.java"
public class com.foxty.basic.Test {
public com.foxty.basic.Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: new #2 // class com/foxty/basic/Test$1-这里创建了一个Test$1的类
3: dup
4: invokespecial #3 // Method com/foxty/basic/Test$1."<init>":()V
7: astore_1
8: return
}
接着再来看看另外一个Test$1.class是什么,从下面反编译出来的代码就知道这个Test$1就是一个ArrayList的子类。结合原来的java代码,就知道这个写法其实就是创建了一个ArrayList的匿名子类而已。里面的那层大括号就相当于你给类加了一个初始化的代码块,这个代码块会自动合并到类的init方法,也就是对象的构造方法里。
isaac-mbp:basic foxty$ javap -c Test\$1.class
Compiled from "Test.java"
final class com.foxty.basic.Test$1 extends java.util.ArrayList<java.lang.String> {
com.foxty.basic.Test$1();
Code:
0: aload_0
1: invokespecial #1 // Method java/util/ArrayList."<init>":()V
4: aload_0
5: ldc #2 // String a
7: invokevirtual #3 // Method add:(Ljava/lang/Object;)Z
10: pop
11: aload_0
12: ldc #4 // String b
14: invokevirtual #3 // Method add:(Ljava/lang/Object;)Z
17: pop
18: return
}
参考:
https://mybatis.org/mybatis-3/zh/java-api.html
https://www.oschina.net/question/2830476_2274044?p=2&sort=default