前言
Java 最早诞生于 1995 年,直到现在都还是最热门的语言之一,那么Java 是怎么满足人们提出的各种后辈语言们的实用功能的呢?语法糖就是其中方式。
解语法糖
Java 为了保证向后兼容又要实现一些新特性非常很不容易,事实上JVM 并不认识这些语法,这些语法糖其实都是编译前的产物,编译阶段就会解语法糖。下面讲一下常见的几种语法糖。
switch 支持 String
switch 本身就支持 int , char 等基本数据类型,在 jdk 1.7 之后 switch 也开始支持 String 和枚举 Enum 类型了,其实内部就是通过语法糖的方式实现的。
反编译一段代码就能看到内部是通过 String 的 hashCode 和 equals 方法实现的。
public class switchDemoString
{
public switchDemoString()
{
}
public static void main(String args[])
{
String str = "world";
String s;
switch((s = str).hashCode())
{
default:
break;
case 99162322:
if(s.equals("hello"))
System.out.println("hello");
break;
case 113318802:
if(s.equals("world"))
System.out.println("world");
break;
}
}
}
这里在 case 完 hashCode 之后还有一次 equals 方法的检查,这是因为哈希可能发生碰撞冲突即两个对象的哈希值一样,所以 switch String 的性能没有基本数据好。
泛型
Java 的泛型是通过类型擦除实现的,即泛型的类型检查只在编辑前检查限制,编译成字节码的时候有个类型擦除的过程,JVM 并不认识泛型类型。
以下代码:
Map<String, String> map = new HashMap<String, String>();
map.put("name", "hollis");
map.put("wechat", "Hollis");
map.put("blog", "www.hollischuang.com");
解语法糖之后会变成:
Map map = new HashMap();
map.put("name", "hollis");
map.put("wechat", "Hollis");
map.put("blog", "www.hollischuang.com");
自动装箱和拆箱
自动装箱的代码
public static void main(String[] args) {
int i = 10;
Integer n = i;
}
反编译后代码如下:
public static void main(String args[])
{
int i = 10;
Integer n = Integer.valueOf(i);
}
三个点
public static void print(String... strs)
{
for (int i = 0; i < strs.length; i++)
{
System.out.println(strs[i]);
}
}
反编译后代码:
public static transient void print(String strs[])
{
for(int i = 0; i < strs.length; i++)
System.out.println(strs[i]);
}
可以看到 ... 相当于是数组实现。
枚举
public enum t {
SPRING,SUMMER;
}
然后我们使用反编译,看看这段代码到底是怎么实现的,反编译后代码内容如下:
public final class T extends Enum
{
private T(String s, int i)
{
super(s, i);
}
public static T[] values()
{
T at[];
int i;
T at1[];
System.arraycopy(at = ENUM$VALUES, 0, at1 = new T[i = at.length], 0, i);
return at1;
}
public static T valueOf(String s)
{
return (T)Enum.valueOf(demo/T, s);
}
public static final T SPRING;
public static final T SUMMER;
private static final T ENUM$VALUES[];
static
{
SPRING = new T("SPRING", 0);
SUMMER = new T("SUMMER", 1);
ENUM$VALUES = (new T[] {
SPRING, SUMMER
});
}
}
内部类
内部类也是个编译时的概念,因为编译之后内部类也是会生成一个
class 文件
总结
Java 的各种语法糖在编译时就规避了很多错误,可以把 bug 早早地扼杀掉,在结合 IDEA 等现代 IDE 可以大大提高开发者的编程体验。在探究内部实现时可以看到都是很巧妙的实现。
网友评论