一个简单的例子:
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 }