Java语法糖 |
您所在的位置:网站首页 › 糖指的是什么意思啊 › Java语法糖 |
语法糖(Syntactic Sugar),也称糖衣语法,是由英国计算机学家 Peter.J.Landin(彼得·兰丁) 发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。语法糖就是对现有语法的一个封装。简而言之,语法糖让程序更加简洁,有更高的可读性。 有意思的是,在编程领域,除了语法糖,还有语法盐和语法糖精的说法,篇幅有限这里不做扩展了。 我们所熟知的编程语言中几乎都有语法糖。很多人说Java是一个“低糖语言”,其实从Java 7开始,Java语言层面上一直在添加各种糖,主要是在“Project Coin”项目下研发。尽管现在Java有人还是认为现在的Java是低糖,未来还会持续向着“高糖”的方向发展。 解语法糖前面提到过,语法糖的存在主要是方便开发人员使用。但是,Java虚拟机并不支持这些语法糖。这些语法糖在编译阶段就会被还原成简单的基础语法结构,这个过程就是解语法糖。 Java中的语法糖只存在于编译期,在编译器将 .java 源文件编译成 .class 字节码时,如果你去看com.sun.tools.javac.main.JavaCompiler的源码,你会发现在compile()中有一个步骤就是调用desugar(),这个方法就是负责解语法糖而实现的。 Java 中最常用的语法糖主要有switch语句支持String与枚举、泛型和类型擦除、自动装箱与拆箱、方法边长参数、枚举、内部类、条件编译、断言、数值字面量、增强for循环、try-with-resources语句、Lambda表达式等。本文主要来分析下这些语法糖背后的原理。一步一步剥去糖衣,看看其本质。 糖块一、switch支持String与枚举从Java 7 开始,Java语言中的语法糖在逐渐丰富,其中一个比较重要的就是Java 7中switch语句开始支持String。 在开始coding之前先科普下,Java中的swith自身原本就支持基本类型。比如int、char等。 对于int类型,直接进行数值的比较。对于char类型则是比较其ascii码。 所以,对于编译器来说,switch中其实只能使用整型,任何类型的比较都要转换成整型。比如byte。short,char(ackii码是整型)以及int。 那么接下来看下switch对String的支持,有以下代码: public class SwitchDemoString { public static void main(String[] args) { String str = "world"; switch (str) { case "hello": System.out.println("hello"); break; case "world": System.out.println("world"); break; default: break; } } }反编译后内容如下: public class SwitchStringDemo { public static void main(String[] args) { String str; String string = str = "world"; int n = -1; switch (string.hashCode()) { case 99162322: { if (!string.equals("hello")) break; n = 0; break; } case 113318802: { if (!string.equals("world")) break; n = 1; } } switch (n) { case 0: { System.out.println("hello"); break; } case 1: { System.out.println("world"); break; } } } }看到这个代码,你知道原来字符串的switch是通过equals()和hashCode()方法来实现的。还好hashCode()方法返回的是int,而不是long。 仔细看下可以发现,进行switch比较的实际是哈希值,然后通过使用equals方法比较进行安全检查,这个检查是必要的,因为哈希可能会发生碰撞。因此它的性能是不如使用枚举进行switch或者使用纯整数常量,但这也不是很差。 糖块二、泛型和类型擦除我们都知道,很多语言都是支持泛型的,但是很多人不知道的是,不同的编译器对于泛型的处理方式是不同的。 通常情况下,一个编译器处理泛型有两种方式:Code specialization和Code sharing。 C++和C#是使用Code specialization的处理机制,而Java使用的是Code sharing的机制。 Code sharing方式为每个泛型类型创建唯一的字节码表示,并且将该泛型类型的实例都映射到这个唯一的字节码表示上。将多种泛型类形实例映射到唯一的字节码表示是通过类型擦除(type erasue)实现的。 也就是说,对于Java虚拟机来说,他根本不认识Map map这样的语法。需要在编译阶段通过类型擦除的方式进行解语法糖。 类型擦除的主要过程如下: 将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。移除所有的类型参数。以下代码: Map map = new HashMap(); map.put("name", "JourWon"); map.put("wechat", "JourWon"); map.put("blog", "https://blog.csdn.net/ThinkWon");解语法糖之后会变成: Map map = new HashMap(); map.put("name", "JourWon"); map.put("wechat", "JourWon"); map.put("blog", "https://blog.csdn.net/ThinkWon");以下代码: public static A max(Collection xs) { Iterator xi = xs.iterator(); A w = xi.next(); while (xi.hasNext()) { A x = xi.next(); if (w.compareTo(x) |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |