导语: 在很长一段时间里面 Java一直被认为是”低糖“的语言 在解释什么叫低糖语言这前 我们需要先了解一下 语法糖的概念 也称 糖衣语法语法糖(英语:Syntactic sugar)是由英国计算机科学家彼得·兰丁发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用。语法糖让程序更加简洁,有更高的可读性。
举例来说,许多程序语言提供专门的语法来对数组中的元素进行引用和更新。从理论上来讲,一个数组元素的引用涉及到两个参数:数组和下标向量,比如这样的表达式:get_array(Array, vector(i, j))。然而,许多语言支持这样直接引用:Array[i, j]。同理,数组元素的更新涉及到三个参数:set_array(Array, vector(i, j), value),但是很多语言提供直接赋值:Array[i, j] = value
不得不说这种语法糖使得程序的可读性与易用性有了很大提高 那作为编程语言界翘楚的Java编程语言自然也有很多的语法糖存在。
一.Java的语法糖是编写期语法糖
怎么理解 编写期语法糖呢?语法糖的存在主要是方便开发人员使用。但其实,Java虚拟机并不支持这些语法糖。这些语法糖在编译阶段就会被还原成简单的基础语法结构,这个过程就是解语法糖。 看过Java虚拟机源码的都知道 虚拟机执行过程中有一步会去调用 desuger()方法进行解语法糖
二.Java语法糖举例
语法糖其实广泛存在于Java语言中 所以近几年Java是低糖语言的声音已经越来越小了 下面我们就深入Java字节码文件去了解和学习Java语法糖
1.语法糖的应用Ⅰ-Java对泛型的支持
Java本身是一门强类型的编程语言 所以Java虚拟机是不支持泛型的 但是为了方便开发人员使用和减少强制类型转换时的出错概率,Java提供了一种叫 编译期泛型的 Java语法糖 正因为虚拟机中没有泛型,只有普通类和普通方法,所有泛型类的类型参数在编译时都会被擦除,泛型类并没有自己独有的Class类对象。比如并不存在 List <T>.class
或是List<Object>.class
,而只有List.class
。
public class SugerTest {
public static void main(String[] args) {
Map<String,String> items = new HashMap<>();
items.put("company","SPD Bank");
}
}
反编译之后的代码其实是
public class SugerTest
{
public SugerTest()
{
}
public static void main(String args[])
{
Map items = new HashMap();
items.put("company", "SPD Bank");
}
}
所以最终的泛型其实是会在编译完成后进行类型擦除的 因为本质上Java是强类型语言 不支持泛类型
了解这个语法糖对我们开发有什么指示和警醒作用呢?虽然Java最终不能支持泛型 但是引入泛型确是非常成功和有必要的 我们都知道 List list=new arrayLIst();虽然这样写很简单 但是代码却很危险 为什么这么说 因为List中虽然可以放入任意元素 但是他们的类型需要一致 例如:
public class SugerTest {
public static void main(String[] args) {
List item= Lists.newArrayList();
int a=1;
String b="@";
item.add(1);
item.add(b);
}
}
上述代码其实是有危险的代码 但是由于我们没有使用泛型导致这个潜在性错误在编译器没有被发现 但是一旦程序运行就有可能会出现异常
2.语法糖的应用Ⅱ-swatch对String的支持
在JDK1.7这前String类型是不能在Swatch语句中作为参数使用的 在JDK1.7引入了相应的语法糖支持
我们都知道 swatch语句的参数只能是int类型的值 有人说 swatch不是还支持 char吗 原因很简单 char类型的Asll-Ⅱ码是int类型数值 布尔类型 本质上是 0和1 所以上述类型天生就可以被swatch支持。那么我们如何让String类型也可以在swatch中使用呢?首先我们想到的就是求String的哈希值 所幸hashCode 函数返回值的确是一个int值 那么问题就变得简单了 于是乎在JDK1.7就自然新增了String作为参数的支持了 我们通过字节码文件转换来看看Java语法糖底层是怎么实现swatch对String的支持的
public