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
这个逻辑很简单,就是简单的invokespecial了ArrayList的<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泛型和编译优化的一个例子的更多相关文章
- 转PostgreSQL 用游标优化的一个例子
一位PG社区的朋友提到的一个应用场景,目前遇到性能问题. 数据结构大概是这样的,包含一个主键,一个数组,一个时间,其他字段. 请求分析: 有检索需求,比较频繁.查找数组中包含某些元素的记录,并按时间排 ...
- Java——泛型
前言 一般的类和方法,使用的都是具体的类型:基本类型或者自定义的类.如果我们要编写出适用于多种类型的通用代码,那么肯定就不能使用具体的类型.前面我们介绍过多态,多态算是一种泛化机制,但是也会拘泥于继承 ...
- 深入理解java泛型
一. 什么是泛型? 泛 型(Generic type 或者 generics)是对 简单的理解,就是对类型的参数化,比如我们定义一个类属性或者实例属性时,往往要指定具体的类型,如Integer.Per ...
- Java - 28 Java 泛型
Java 泛型 如果我们只写一个排序方法,就能够对整型数组.字符串数组甚至支持排序的任何类型的数组进行排序,这该多好啊. Java泛型方法和泛型类支持程序员使用一个方法指定一组相关方法,或者使用一个类 ...
- 20180826(03)-Java泛型
Java 泛型 如果我们只写一个排序方法,就能够对整形数组.字符串数组甚至支持排序的任何类型的数组进行排序,这该多好啊. Java泛型方法和泛型类支持程序员使用一个方法指定一组相关方法,或者使用一个类 ...
- Java泛型的一些限制
本文主要參考<Java编程思想(第4版)>的Java泛型章节,仅当一个简单的读书笔记. 和C++泛型对照,Java泛型仅仅是一种编译期间的擦拭机制. 这是因为考虑到和曾经的兼容而考虑的一种 ...
- Java泛型读书笔记 (二)
关于Java泛型擦除后,继承一个泛型类带来的问题 有如下泛型类Pair: public class Pair<T> { private T second; private T first; ...
- java泛型笔记一
名词:泛型类 泛型方法 原始类型 子类型 版本 参数化类型 通配符类型 超类通配 子类通配 全通配 定义变量 创建对象 检查模板 类型实参 类型形参 补充 替代语法特征:尖括号括起来的类型参数表 // ...
- Java泛型反射机制(二)
/** * @author Administrator * 好处:泛型:1安全 2减少代码重用率 */ package com.test; import java.lang.reflect.Metho ...
随机推荐
- Python语言上机题实现方法(持续更新...)
Python语言上机题实现方法(持续更新...) 1.[字符串循环左移]给定一个字符串S,要求把S的前k个字符移动到S的尾部,如把字符串"abcdef"前面的2个字符'a'.'b' ...
- nginx内置高可用配置与第三方高可用模块nginx_ustream_check_mudule配置
1. nginx 第三方高可用模块 IP 备注 10.0.0.63 proxy 10.0.0.64 web1 10.0.0.65 web2 这里会讲解一些nignx常用高可用方案,以及引入第三方高可用 ...
- pgsql中的行锁
pgsql中的行锁 前言 用户可见的锁 regular Lock 行级别 FOR UPDATE FOR NO KEY UPDATE FOR SHARE FOR KEY SHARE 测试下加锁之后的数据 ...
- conda命令详解
显示已有环境信息 conda info --envs 创建环境 conda create --name [环境名] python=[版本号] 删除环境 conda remove --name [环境名 ...
- 宏定义#define和内联函数inline的区别
1 宏定义在预编译的时候进行字符串替换.内联函数在编译的时候进行函数展开. 2 宏定义没有类型检查.内联函数会进行参数列表.返回值等类型检查.
- 小程序以及H5页面上IphoneX底部安全区域小黑条适配问题
背景 公司项目开发中,发现iPhoneX上吸底元素存在被小黑条遮挡的问题 原因 在苹果 iPhoneX .iPhone XR等机型上,物理Home键被取消,改为底部小黑条替代home键功能,从而导致吸 ...
- 【python系统学习14】类的继承与创新
目录: 目录: [toc] 类的继承 子类和父类 继承的写法 继承示例 父类可以被无限个子类所继承 子类实例可调用父类属性和方法 类的始祖(根类) 根类 - object 实例归属判断 - isins ...
- Android 修改应用程序字体
在网上搜索了相关资料,研究了两种算是比较快速的改变程序字体的方法,好,先来介绍着两种方法. 首先第一种方法是重写控件(以Textview为例): 1.Android在写程序的时候谷歌早已将所有字体都默 ...
- Jenkins 批量创建任务的三种方法
最近,要搭建多套测试环境,需要把 Jenkins 中 dev 视图下的所有任务批量复制到 sit 等视图下. 说明 Jenkins 任务名称规则为:[测试环境标识]-[工程名称],如:dev-daod ...
- 经典算法之归并排序——python和JS实现
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:韩忠康 PS:如有需要Python学习资料的小伙伴可以加点击下方链接自 ...