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

Java泛型和编译优化的一个例子的更多相关文章

  1. 转PostgreSQL 用游标优化的一个例子

    一位PG社区的朋友提到的一个应用场景,目前遇到性能问题. 数据结构大概是这样的,包含一个主键,一个数组,一个时间,其他字段. 请求分析: 有检索需求,比较频繁.查找数组中包含某些元素的记录,并按时间排 ...

  2. Java——泛型

    前言 一般的类和方法,使用的都是具体的类型:基本类型或者自定义的类.如果我们要编写出适用于多种类型的通用代码,那么肯定就不能使用具体的类型.前面我们介绍过多态,多态算是一种泛化机制,但是也会拘泥于继承 ...

  3. 深入理解java泛型

    一. 什么是泛型? 泛 型(Generic type 或者 generics)是对 简单的理解,就是对类型的参数化,比如我们定义一个类属性或者实例属性时,往往要指定具体的类型,如Integer.Per ...

  4. Java - 28 Java 泛型

    Java 泛型 如果我们只写一个排序方法,就能够对整型数组.字符串数组甚至支持排序的任何类型的数组进行排序,这该多好啊. Java泛型方法和泛型类支持程序员使用一个方法指定一组相关方法,或者使用一个类 ...

  5. 20180826(03)-Java泛型

    Java 泛型 如果我们只写一个排序方法,就能够对整形数组.字符串数组甚至支持排序的任何类型的数组进行排序,这该多好啊. Java泛型方法和泛型类支持程序员使用一个方法指定一组相关方法,或者使用一个类 ...

  6. Java泛型的一些限制

    本文主要參考<Java编程思想(第4版)>的Java泛型章节,仅当一个简单的读书笔记. 和C++泛型对照,Java泛型仅仅是一种编译期间的擦拭机制. 这是因为考虑到和曾经的兼容而考虑的一种 ...

  7. Java泛型读书笔记 (二)

    关于Java泛型擦除后,继承一个泛型类带来的问题 有如下泛型类Pair: public class Pair<T> { private T second; private T first; ...

  8. java泛型笔记一

    名词:泛型类 泛型方法 原始类型 子类型 版本 参数化类型 通配符类型 超类通配 子类通配 全通配 定义变量 创建对象 检查模板 类型实参 类型形参 补充 替代语法特征:尖括号括起来的类型参数表 // ...

  9. Java泛型反射机制(二)

    /** * @author Administrator * 好处:泛型:1安全 2减少代码重用率 */ package com.test; import java.lang.reflect.Metho ...

随机推荐

  1. MyBatis 学习笔记(2)

    1.执行SQL时传递多参数 如果 parameterType 使用 map 类型,即 parameterType="map",那么可以使用注解(@Param)方式传递参数,而最好不 ...

  2. windows上jmeter目录结构功能

    1.bin :存储了jmeter的可执行程序,如启动 2.lib:存储了jmeter的整合的功能(如.jar文件程序) 3.启动jmeter:双击bin\apachejmeter.jar jmeter ...

  3. xargs与exec区别

    平时使用find命令查找出文件的时候有时候后面有时候用-exec有时候用管道加xargs,这2个到底有什么不同?下面就这2个的不同做简单介绍. 零.实验环境 [root@osker /]# find ...

  4. Golang中的Gosched、Goexit、GOMAXPROCS

    Golang进程权限调度包runtime三大函数Gosched,Goexit,GOMaXPROCS runtime.Gosched(),用于让出CPU时间片,让出当前goroutine的执行权限,调度 ...

  5. 不错的spring学习博客

    http://blog.csdn.net/xyh820/article/details/7303330/

  6. Java团队课程设计——基于学院的搜索引擎

    团队名称.团队成员介绍.任务分配,团队成员课程设计博客链接 姓名 成员介绍 任务分配 课程设计博客地址 谢晓淞(组长) 团队输出主力 爬虫功能实现,Web前端设计及其后端衔接 爬虫:https://w ...

  7. AJ学IOS(55)多线程网络之图片下载框架之SDWebImage

    AJ分享,必须精品 效果: 代码: - (NSArray *)apps { if (!_apps) { NSArray *dictArray = [NSArray arrayWithContentsO ...

  8. Docker-CentOS系统安装Docker

    上一节,我们介绍了安装虚拟机及操作系统,本文再详细描述安装docker的命令. 前提条件 虚拟机系统:CentOS,并且虚拟机能连通外网. 另外,虚拟机最好配置上阿里的镜像源,点此链接,进入cento ...

  9. 45道SQL数据题详解1

    准备阶段: 创建表: //创建学生表,前面的s表示学生,相应的标签前面加t表示老师 CREATE TABLE students (sno VARCHAR(3) NOT NULL, sname VARC ...

  10. Python 七步捉虫法

    了解一些技巧助你减少代码查错时间. -- Maria Mckinley 在周五的下午三点钟(为什么是这个时间?因为事情总会在周五下午三点钟发生),你收到一条通知,客户发现你的软件出现一个错误.在有了初 ...