Java 语法糖

2018-02-13  本文已影响15人  RobertCrazying

前言

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 可以大大提高开发者的编程体验。在探究内部实现时可以看到都是很巧妙的实现。

参考链接:https://mp.weixin.qq.com/s/BNWEE7wFc6ZvDAqJQrZRaA

上一篇下一篇

猜你喜欢

热点阅读