public class Main { public static void main(String[] args) { ArrayList<String> strList = new ArrayList<String>(); Type type = ((ParameterizedType)strList.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; System.out.println(type); } }
public class Main { public static void main(String[] args) { ArrayList<String> strList = new ArrayList<String>(){}; Type type = ((ParameterizedType)strList.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; System.out.println(type); } }
這兩個例子惟一的區別是後者的new ArrayList<String>(){}
初始化strList
的時候帶了{}
執行了賦初值,雖然語法層面沒有什麼區別,可是在編譯以後的結果卻徹底不同。並且執行的結果也徹底不同,
前者執行結果:java
E
後者執行結果:code
class java.lang.String
前者的編譯結果:ip
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: new #2 // class java/util/ArrayList 3: dup 4: invokespecial #3 // Method java/util/ArrayList."<init>":()V 7: astore_1 8: aload_1 9: invokevirtual #4 // Method java/lang/Object.getClass:()Ljava/lang/Class; 12: invokevirtual #5 // Method java/lang/Class.getGenericSuperclass:()Ljava/lang/reflect/Type; 15: checkcast #6 // class java/lang/reflect/ParameterizedType 18: invokeinterface #7, 1 // InterfaceMethod java/lang/reflect/ParameterizedType.getActualTypeArguments:()[Ljava/lang/reflect/Type; 23: iconst_0 24: aaload 25: astore_2 26: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 29: aload_2 30: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 33: return
這個邏輯很簡單,就是簡單的invokespecial
了ArrayList
的<init>()
方法。ci
後者的編譯結果:get
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: new #2 // class Main$1 3: dup 4: invokespecial #3 // Method Main$1."<init>":()V 7: astore_1 8: aload_1 9: invokevirtual #4 // Method java/lang/Object.getClass:()Ljava/lang/Class; 12: invokevirtual #5 // Method java/lang/Class.getGenericSuperclass:()Ljava/lang/reflect/Type; 15: checkcast #6 // class java/lang/reflect/ParameterizedType 18: invokeinterface #7, 1 // InterfaceMethod java/lang/reflect/ParameterizedType.getActualTypeArguments:()[Ljava/lang/reflect/Type; 23: iconst_0 24: aaload 25: astore_2 26: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 29: aload_2 30: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 33: return
這裏就奇怪了,加了{}
以後居然生成了內部類Main$1
:it
final class Main$1 extends java.util.ArrayList<java.lang.String> ... { Main$1(); descriptor: ()V flags: Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/util/ArrayList."<init>":()V 4: return LineNumberTable: line 8: 0 } Signature: #9 // Ljava/util/ArrayList<Ljava/lang/String;>; ...
是java.util.ArrayList<java.lang.String>
的子類,這也就解釋了後者的執行結果爲什麼能夠解析到strList
的泛型參數化類型是java.lang.String
了,由於它的實際類型在JVM執行的時候清楚地被標記成了內部類Main$1
這個java.util.ArrayList<java.lang.String>
的子類。而前者的strList
的泛型參數化類型已經被擦除掉了。io