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