转:【深入Java虚拟机】之六:Java语法糖
转载请注明出处:http://blog.csdn.net/ns_code/article/details/18011009
语法糖(Syntactic Sugar),也称糖衣语法,是由英国计算机学家Peter.J.Landin发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。Java中最常用的语法糖主要有泛型、变长参数、条件编译、自动拆装箱、内部类等。虚拟机并不支持这些语法,它们在编译阶段就被还原回了简单的基础语法结构,这个过程成为解语法糖。
泛型是JDK1.5之后引入的一项新特性,Java语言在还没有出现泛型时,只能通过Object是所有类型的父类和类型强制转换这两个特点的配合来实现泛型的功能,这样实现的泛型功能要在程序运行期才能知道Object真正的对象类型,在Javac编译期,编译器无法检查这个Object的强制转型是否成功,这便将一些风险转接到了程序运行期中。
Java语言在JDK1.5之后引入的泛型实际上只在程序源码中存在,在编译后的字节码文件中,就已经被替换为了原来的原生类型,并且在相应的地方插入了强制转型代码,因此对于运行期的Java语言来说,ArrayList<String>和ArrayList<Integer>就是同一个类。所以泛型技术实际上是Java语言的一颗语法糖,Java语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型被称为伪泛型。
下面是一段简单的Java泛型代码:
- Map<Integer,String> map = new HashMap<Integer,String>();
- map.put(1,"No.1");
- map.put(2,"No.2");
- System.out.println(map.get(1));
- System.out.println(map.get(2));
将这段Java代码编译成Class文件,然后再用字节码反编译工具进行反编译后,将会发现泛型都变回了原生类型,如下面的代码所示:
- Map map = new HashMap();
- map.put(1,"No.1");
- map.put(2,"No.2");
- System.out.println((String)map.get(1));
- System.out.println((String)map.get(2));
为了更详细地说明类型擦除,再看如下代码:
- import java.util.List;
- public class FanxingTest{
- public void method(List<String> list){
- System.out.println("List String");
- }
- public void method(List<Integer> list){
- System.out.println("List Int");
- }
- }
当我用Javac编译器编译这段代码时,报出了如下错误:
FanxingTest.java:3: 名称冲突:method(java.util.List<java.lang.String>) 和 method
(java.util.List<java.lang.Integer>) 具有相同疑符
public void method(List<String> list){
^
FanxingTest.java:6: 名称冲突:method(java.util.List<java.lang.Integer>) 和 metho
d(java.util.List<java.lang.String>) 具有相同疑符
public void method(List<Integer> list){
^
2 错误
这是因为泛型List<String>和List<Integer>编译后都被擦除了,变成了一样的原生类型List,擦除动作导致这两个方法的特征签名变得一模一样,在Class类文件结构一文中讲过,Class文件中不能存在特征签名相同的方法。
把以上代码修改如下:
- import java.util.List;
- public class FanxingTest{
- public int method(List<String> list){
- System.out.println("List String");
- return 1;
- }
- public boolean method(List<Integer> list){
- System.out.println("List Int");
- return true;
- }
- }
发现这时编译可以通过了(注意:Java语言中true和1没有关联,二者属于不同的类型,不能相互转换,不存在C语言中整数值非零即真的情况)。两个不同类型的返回值的加入,使得方法的重载成功了。这是为什么呢?
我们知道,Java代码中的方法特征签名只包括了方法名称、参数顺序和参数类型,并不包括方法的返回值,因此方法的返回值并不参与重载方法的选择,这样看来为重载方法加入返回值貌似是多余的。对于重载方法的选择来说,这确实是多余的,但我们现在要解决的问题是让上述代码能通过编译,让两个重载方法能够合理地共存于同一个Class文件之中,这就要看字节码的方法特征签名,它不仅包括了Java代码中方法特征签名中所包含的那些信息,还包括方法返回值及受查异常表。为两个重载方法加入不同的返回值后,因为有了不同的字节码特征签名,它们便可以共存于一个Class文件之中。
自动拆装箱、变长参数等语法糖也都是在编译阶段就把它们该语法糖结构还原为了原生的语法结构,因此在Class文件中也只存在其对应的原生类型,这里不再一一说明。
转:【深入Java虚拟机】之六:Java语法糖的更多相关文章
- Java的12个语法糖【转】
本文转载自公众号 Hollis 原创: 会反编译的 Hollis 侵权删 本文从 Java 编译原理角度,深入字节码及 class 文件,抽丝剥茧,了解 Java 中的语法糖原理及用法,帮助大家在学 ...
- 深入理解 Java 虚拟机——走近 Java
1.1 - 概述 Java 总述:Java 不仅是一门编程语言,还是一个由一系列 计算机软件 和 规范 形成的技术体系,这个技术体系提供了完整的用于软件开发和跨平台部署的支持环境,并广泛应用于 嵌入式 ...
- 《深入理解Java虚拟机》-Java代码是如何运行的
问题一:Java与C++区别 1.Java需要运行时环境,包括Java虚拟机以及Java核心类库等. 2.C++无需额外的运行时,通常编译后的代码可以让机器直接读取,即机器码 问题一:Java为什么要 ...
- 深入理解Java虚拟机之Java内存区域与内存溢出异常
Java内存区域与内存溢出异常 运行时数据区域 程序计数器 用于记录从内存执行的下一条指令的地址,线程私有的一小块内存,也是唯一不会报出OOM异常的区域 Java虚拟机栈 Java虚拟机栈(Java ...
- 深入理解Java虚拟机-走进Java
一.Java技术体系 从广义上讲, Clojure. JRuby. Groovy等运行于Java虚拟机上的语言及其相关的程序都属于Java技术体系中的一员. 如果仅从传统意义上来看, Sun官方所定义 ...
- Java中部分常见语法糖
语法糖(Syntactic Sugar),也称糖衣语法,指在计算机语言中添加的某种语法,这种语法对语言本身功能来说没有什么影响,只是为了方便程序员的开发,提高开发效率.说白了,语法糖就是对现有语法的一 ...
- 《深入理解Java虚拟机》 Java对象的生命周期
Java虚拟机运行时数据区 方法区:存储 类信息.常量.静态变量.即使编译器编译后的代码等数据,也有别名叫做非堆. 方法区其中有包含有 运行时常量池,用于存放编译期生成的各种字面量和符号引用.其中, ...
- 《深入理解Java虚拟机》Java内存区域与内存溢出异常
注:“蓝色加粗字体”为书本原语 先来一张JVM运行时数据区域图,再接下来一一分析各区域功能: 程序计数器 程序计数器(program Counter Register)是一块较小的内存空间,它可以 ...
- 深入理解java虚拟机【Java虚拟机类生命周期】
C/C++等纯编译语言从源码到最终执行一般要经历:编译.连接和运行三个阶段,连接是在编译期间完成,而java在编译期间仅仅是将源码编译为Java虚拟机可以识别的字节码Class类文件,Java虚拟机对 ...
- 深入理解java虚拟机【Java Class类文件结构】
Java语言从诞生之时就宣称一次编写,到处运行的跨平台特性,其实现原理是源码文件并没有直接编译成机器指令,而是编译成Java虚拟机可以识别和运行的字节码文件(Class类文件,*.class),字节码 ...
随机推荐
- 如何快速高效地完成一个Android项目?
本文的内容有别于之前文章中纯技术的探讨,会从业务逻辑.技术.团队和方法论的角度探讨如何快速高效地完成一个Android项目.当然,快速高效是有前提的,第一,本文依然是从研发的角度来谈如何把控项目的,而 ...
- Vue事件处理
前面的话 Vue事件监听的方式貌似违背了关注点分离(separation of concern)的传统理念.实际上,所有的Vue.js事件处理方法和表达式都严格绑定在当前视图的ViewModel上,它 ...
- 【HTTP权威指南】第三章-HTTP报文
HTTP是因特网的信使,报文就是信使运送的包裹. 这一章包含: 报文如何流动 报文的三个组成部分(起始行,首部,实体的主体部分) 请求报文和响应报文的区别 请求报文支持的各种功能(方法) 响应报文返回 ...
- .net core 2.0学习笔记(一):开发运行环境搭建
期待已久的.net core 2.0终于发布了!大家等的花儿都谢了. 不过比预期提前了一个多月,这在微软历史上还真的不多见.按照历史经验看,2.0版本应该比较靠谱,我猜这也是社区非常火爆的原因吧.下面 ...
- Xen创建新虚拟机
一.添加一个ISO存储: 右键选择"New Storage Repository-" 选择"ISO Library"中的"Windows File S ...
- Oracle impdp通过network_link不落地方式导入数据
--Oracle impdp通过network_link不落地方式导入数据 -----------------------------------------------------2014/01/1 ...
- MySQL数据库 —子查询,联合查询
一 使用IN关键字的子查询 1.查询游戏类型是'棋牌类' 的游戏的分数信息 游戏分数表中并未包含游戏类型信息 思路一:采用链接查询 思路二: 分两步进行,首先找到所以'棋牌类'游戏的编号,再以这一组编 ...
- MVC5+EF6 完整教程17--升级到EFCore2.0
EF Core 2.0上周已经发布了,我们也升级到core 文章内容基于vs2017,请大家先安装好vs2017(15.3). 本篇文章主要讲下差异点,跟之前一样的就不再重复了. 文章目录(差异点): ...
- 安装完iis后本机用IP可以访问,别的电脑不能访问
局域网IIS无法访问的解决方法 无法访问局域网内其它电脑中的IIS,自己可以访问,但别的电脑不行一般发生这种情况时操作系统是XP第二版. 具体操作如下:1.打开控制面版2.打开Windows防火墙 5 ...
- 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——收流篇:(一)简介
关于实时流媒体传输的开源库,目前流行的主要有两个:live555和jrtplib. 其中live555将rtp.rtcp和rtsp的传输协议实现集于一身,功能齐全,是个超强的集合体.但是对于嵌入式系统 ...