zoukankan      html  css  js  c++  java
  • Java泛型和编译优化的一个例子

    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的时候带了{}执行了赋初值,虽然语法层面没有什么区别,但是在编译之后的结果却完全不一样。而且执行的结果也完全不一样,
    前者执行结果:

    E

    后者执行结果:

    class java.lang.String

    前者的编译结果:

    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

    这个逻辑很简单,就是简单的invokespecialArrayList<init>()方法。

    后者的编译结果:

    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:

    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的泛型参数化类型已经被擦除掉了。

  • 相关阅读:
    mysql数据库常用指令
    解决windows的mysql无法启动 服务没有报告任何错误的经验。
    “Can't open file for writing”或“operation not permitted”的解决办法
    启动Apache出现错误Port 80 in use by "Unable to open process" with PID 4!
    如何打开windows的服务services.msc
    常见的HTTP状态码 404 500 301 200
    linux系统常用的重启、关机指令
    (wifi)wifi移植之命令行调试driver和supplicant
    linux(debian)安装USB无线网卡(tp-link TL-WN725N rtl8188eu )
    alloc_chrdev_region申请一个动态主设备号,并申请一系列次设备号
  • 原文地址:https://www.cnblogs.com/twodog/p/12136096.html
Copyright © 2011-2022 走看看