JAVA語法糖

談一談JAVA語法糖

上週在聽大牛分享JVM編譯優化時,提到了在編譯階段會進行的一個步驟:解語法糖。他提出了一個問題是:JAVA裏有哪些語法糖,聽到這個問題,似乎很容易回答,因爲我們都知道java有很多語法糖,但話到嘴邊,也就只能想起字符串拼接和foreach來,果然,沒有經過系統的梳理,一些聽起來簡單的知識點也會難倒你,所以我來梳理一下,看java裏到底有哪些語法糖。

概述

在搜狗百科中,語法糖含義解釋如下:語法糖(Syntactic sugar),也譯爲糖衣語法,是由英國計算機科學家彼得·約翰·蘭達(Peter J. Landin)發明的一個術語,指計算機語言中添加的某種語法,這種語法對語言的功能並沒有影響,但是更方便程序員使用。通常來說使用語法糖能夠增加程序的可讀性,從而減少程序代碼出錯的機會。

從概念上可以看出來,簡單地說就是通過更簡單的語法實現原有功能,對語言功能沒有影響。以java來說就是某個語法可能JVM不支持,但是編譯器可以將語法轉換成基礎語法以實現功能。相當於快捷方式。

有哪些語法糖

下面我們寫一些語法糖使用,通過反編譯看看他們是怎麼實現的。

增強for循環

    /**
     * 增強for循環
     */
    public void forTest() {
        List<String> stringList = Arrays.asList("A", "B");
        for (String str :stringList) {
            System.out.println(str);
        }
    }

反編譯class文件後

    public void forTest() {
        List<String> stringList = Arrays.asList("A", "B");
        Iterator var2 = stringList.iterator();

        while(var2.hasNext()) {
            String str = (String)var2.next();
            System.out.println(str);
        }

    }

通過Iterator實現,這裏在分析fail-fast機制時提過,不能在增強for循環中進行集合的增刪操作,否則會拋異常。

switch(String)

/**
     * switch(String)
     */
    public int switchString(String str) {
        switch (str){
            case "A":
               return 1;
            case "B":
                return 2;
            default:
                return 0;
        }
    }
public int switchString(String str) {
        byte var3 = -1;
        switch(str.hashCode()) {
        case 65:
            if (str.equals("A")) {
                var3 = 0;
            }
            break;
        case 66:
            if (str.equals("B")) {
                var3 = 1;
            }
        }

        switch(var3) {
        case 0:
            return 1;
        case 1:
            return 2;
        default:
            return 0;
        }
    }

可以看到switch(String)是轉爲了switch(byte),之前單獨分析過這裏的機制。

條件編譯

    /**
     * 條件編譯
     */
    public void ifTest() {
        if (true)  {
            System.out.println("1");
        } else {
            System.out.println("2");
        }
    }
    public void ifTest() {
        System.out.println("1");
    }

當條件爲常量時,一定不會執行的分支會自動清除。

可變參數

    /**
     * 可變參數
     * @param strings
     */
    public void strings(String... strings) {
        for (String s : strings) {
            System.out.println(s);
        }
    }
    public void strings(String... strings) {
        String[] var2 = strings;
        int var3 = strings.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            String s = var2[var4];
            System.out.println(s);
        }

    }

可變參數實際是變長數組

泛型

    /**
     * 泛型
     */
    public void listTest() {
        List<String> list = new ArrayList<String>();
        int i = list.size();
    }
    public void listTest() {
        List<String> list = new ArrayList();
        int i = list.size();
    }

可以看到,泛型參數已經被擦除了。

lambda表達式

    /**
     * lambda表達式
     */
    public void lambdaTest() {
        List<String> list = new ArrayList<>();
        list = list.stream().distinct().collect(Collectors.toCollection(LinkedList::new));
    }

try with resource

    /**
     * try with resource
     */
    public void tryResourceTest() throws IOException {
        try(StringWriter writer = new StringWriter()) {
            writer.write(1);
        }
    }
public void tryResourceTest() throws IOException {
        StringWriter writer = new StringWriter();
        Throwable var2 = null;

        try {
            writer.write(1);
        } catch (Throwable var11) {
            var2 = var11;
            throw var11;
        } finally {
            if (writer != null) {
                if (var2 != null) {
                    try {
                        writer.close();
                    } catch (Throwable var10) {
                        var2.addSuppressed(var10);
                    }
                } else {
                    writer.close();
                }
            }

        }

    }

Try with resource是自動幫你加上finally,並且調用closeable接口裏的close方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章