談談Java中的文法糖__Java

來源:互聯網
上載者:User

文法糖(Syntactic Sugar),也稱糖衣文法,指在電腦語言中添加的某種文法,這種文法對語言本身功能來說沒有什麼影響,只是為了方便程式員的開發,提高開發效率。說白了,文法糖就是對現有文法的一個封裝。

Java作為一種與平台無關的進階語言,當然也含有文法糖,這些文法糖並不被虛擬機器所支援,在編譯成位元組碼階段就自動轉換成簡單常用文法。一般來說Java中的文法糖主要有以下幾種:
1. 泛型與類型擦除
2. 自動裝箱與拆箱,變長參數、
3. 增強for迴圈
4. 內部類與枚舉類 泛型與類型擦除

Java語言並不是一開始就支援泛型的。在早期的JDK中,只能通過Object類是所有類型的父類和強制類型轉換來實現泛型的功能。強制類型轉換的缺點就是把編譯期間的問題延遲到運行時,JVM並不能為我們提供編譯期間的檢查。

在JDK1.5中,Java語言引入了泛型機制。但是這種泛型機制是通過類型擦除來實現的,即Java中的泛型只在程式原始碼中有效(原始碼階段提供類型檢查),在編譯後的位元組碼中自動用強制類型轉換進行替代。也就是說,Java語言中的泛型機制其實就是一顆文法糖,相較與C++、C#相比,其泛型實現實在是不那麼優雅。

/*** 在原始碼中存在泛型*/public static void main(String[] args) {    Map<String,String> map = new HashMap<String,String>();    map.put("hello","你好");    String hello = map.get("hello");    System.out.println(hello);}

當上述原始碼被編譯為class檔案後,泛型被擦除且引入強制類型轉換

public static void main(String[] args) {    HashMap map = new HashMap(); //類型擦除    map.put("hello", "你好");    String hello = (String)map.get("hello");//強制轉換    System.out.println(hello);}
自動裝箱與拆箱

Java中的自動裝箱與拆箱指的是基礎資料型別 (Elementary Data Type)與他們的封裝類型之間的相互轉換。

我們知道Java是一門物件導向的語言,在Java世界中有一句話是這麼說的:“萬物皆對象”。但是Java中的基礎資料型別 (Elementary Data Type)卻不是對象,他們不需要進行new操作,也不能調用任何方法,這在使用的時候有諸多不便。因此Java為這些基本類型提供了封裝類,並且為了使用方便,提供了自動裝箱與拆箱功能。自動裝箱與拆箱在使用的過程中,其實是一個文法糖,內部還是調用了相應的函數進行轉換。

下面代碼示範了自動裝箱和拆箱功能

public static void main(String[] args) {    Integer a = 1;    int b = 2;    int c = a + b;    System.out.println(c);}

經過編譯後,代碼如下

public static void main(String[] args) {    Integer a = Integer.valueOf(1); // 自動裝箱    byte b = 2;    int c = a.intValue() + b;//自動拆箱    System.out.println(c);}
變長參數

所謂變長參數,就是方法可以接受長度不定確定的參數

變長參數特性是在JDK1.5中引入的,使用變長參數有兩個條件,一是變長的那一部分參數具有相同的類型,二是變長參數必須位於方法參數列表的最後面。變長參數同樣是Java中的文法糖,其內部實現是Java數組。

public class Varargs {    public static void print(String... args) {        for(String str : args){            System.out.println(str);        }    }    public static void main(String[] args) {        print("hello", "world");    }}

編譯為class檔案後如下,從中可以很明顯的看出變長參數內部是通過數組實現的

public class Varargs {    public Varargs() {    }    public static void print(String... args) {        String[] var1 = args;        int var2 = args.length;        //增強for迴圈的數組實現方式        for(int var3 = 0; var3 < var2; ++var3) {            String str = var1[var3];            System.out.println(str);        }    }    public static void main(String[] args) {        //變長參數轉換為數組        print(new String[]{"hello", "world"});    }}
增強for迴圈

增強for迴圈與普通for迴圈相比,功能更強並且代碼更簡潔

增強for迴圈的對象要麼是一個數組,要麼實現了Iterable介面。這個文法糖主要用來對數組或者集合進行遍曆,其在迴圈過程中不能改變集合的大小。

public static void main(String[] args) {    String[] params = new String[]{"hello","world"};    //增強for迴圈對象為數組    for(String str : params){        System.out.println(str);    }    List<String> lists = Arrays.asList("hello","world");    //增強for迴圈對象實現Iterable介面    for(String str : lists){        System.out.println(str);    }}

編譯後的class檔案為

public static void main(String[] args) {   String[] params = new String[]{"hello", "world"};   String[] lists = params;   int var3 = params.length;   //數組形式的增強for退化為普通for   for(int str = 0; str < var3; ++str) {       String str1 = lists[str];       System.out.println(str1);   }   List var6 = Arrays.asList(new String[]{"hello", "world"});   Iterator var7 = var6.iterator();   //實現Iterable介面的增強for使用iterator介面進行遍曆   while(var7.hasNext()) {       String var8 = (String)var7.next();       System.out.println(var8);   }}
內部類

內部類就是定義在一個類內部的類

Java語言中之所以引入內部類,是因為有些時候一個類只在另一個類中有用,我們不想讓其在另外一個地方被使用。內部類之所以是文法糖,是因為其只是一個編譯時間的概念,一旦編譯完成,編譯器就會為內部類產生一個單獨的class檔案,名為outer$innter.class。

public class Outer {    class Inner{    }}

使用javac編譯後,產生兩個class檔案Outer.class和Outer$Inner.class,其中Outer$Inner.class的內容如下:

class Outer$Inner {    Outer$Inner(Outer var1) {        this.this$0 = var1;    }}

內部類分為四種:成員內部類、局部內部類、匿名內部類、靜態內部類,每一種都有其用法,這裡就不介紹了 枚舉類型

枚舉類型就是一些具有相同特性的類常量

java中類的定義使用class,枚舉類的定義使用enum。在Java的位元組碼結構中,其實並沒有枚舉類型,枚舉類型只是一個文法糖,在編譯完成後被編譯成一個普通的類。這個類繼承java.lang.Enum,並被final關鍵字修飾。

public enum Fruit {    APPLE,ORINGE}

使用jad對編譯後的class檔案進行反編譯後得到:

//繼承java.lang.Enum並聲明為finalpublic final class Fruit extends Enum{    public static Fruit[] values()    {        return (Fruit[])$VALUES.clone();    }    public static Fruit valueOf(String s)    {        return (Fruit)Enum.valueOf(Fruit, s);    }    private Fruit(String s, int i)    {        super(s, i);    }    //枚舉類型常量    public static final Fruit APPLE;    public static final Fruit ORANGE;    private static final Fruit $VALUES[];//使用數組進行維護    static    {        APPLE = new Fruit("APPLE", 0);        ORANGE = new Fruit("ORANGE", 1);        $VALUES = (new Fruit[] {            APPLE, ORANGE        });    }}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.