<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    Java新特性:數(shù)據(jù)類型可以扔掉了?

    共 2998字,需瀏覽 6分鐘

     ·

    2020-10-03 08:05

    在很久很久以前,我們寫代碼時(shí)要慎重的考慮變量的數(shù)據(jù)類型,比如下面這些:

    枚舉:盡管在 JDK 5 中增加了枚舉類型,但是 Class 文件常量池的 CONSTANT_Class_info 類型常量并沒有發(fā)生任何語義變化,仍然是代表一個(gè)類或接口的符號(hào)引用,沒有加入枚舉,也沒有增加過“CONSTANT_Enum_info”之類的“枚舉符號(hào)引用”常量。所以使用 enum 關(guān)鍵字定義常量,盡管從 Java 語法上看起來與使用 class 關(guān)鍵字定義類、使用 interface 關(guān)鍵字定義接口是同一層次的,但實(shí)際上這是由 Javac 編譯器做出來的假象,從字節(jié)碼的角度來看,枚舉僅僅是一個(gè)繼承于 java.lang.Enum、自動(dòng)生成了 values() 和 valueOf() 方法的普通 Java 類而已,因此枚舉也歸為引用類型了。

    然而到了 JDK 10 時(shí),我們就有了新的選擇,JDK 10 中新增了 var 局部變量推斷的功能,使用它我們可以很 happy 的忘記數(shù)據(jù)類型這件事了,那它是如何使用的呢?接下來我們一起來看。

    1、使用對(duì)比

    接下來我們就使用對(duì)比的方式,來體會(huì)一下 var?的作用。

    場景一:定義字符串

    舊寫法:

    String?str?=?"Hello,?Java.";

    新寫法:

    var?s?=?"Hello,?Java.";

    PS:這里的舊寫法指的是 JDK 10 之前的版本,而新寫法指的是 JDK 10 以后(包含 JDK 10)的版本。

    場景二:數(shù)值相加

    舊寫法:

    int?num1?=?111;
    double?num2?=?555.666d;
    double?num3?=?num1?+?num2;
    System.out.println(num3);

    PS:當(dāng)遇到不同類型相加時(shí)(int+ double)會(huì)發(fā)生數(shù)據(jù)類型向上轉(zhuǎn)型,因此 num3?就會(huì)升級(jí)為 double?類型。

    新寫法:

    var?n1?=?111L;
    var?n2?=?555.666;
    var?n3?=?n1?+?n2;
    System.out.println(n3);

    場景三:集合

    舊寫法:

    List?list?=?new?ArrayList<>();
    list.add("Hello");
    list.add("Java");

    新寫法:

    var?list?=?new?ArrayList<>();
    list.add("Hello");
    list.add("Java");

    場景四:循環(huán)

    舊寫法:

    for?(Object?item?:?list)?{
    ????System.out.println("item:"?+?item);
    }
    for?(int?i?=?0;?i?10
    ;?i++)?{
    ????//?do?something...
    }

    新寫法:

    for?(var?item?:?list)?{
    ????System.out.println("item:"?+?item);
    }
    for?(var?i?=?0;?i?10
    ;?i++)?{
    ????//?do?something...
    }

    場景五:配合 Lambda 使用

    舊寫法:

    List?flist?=?list.stream().filter(v?->
    ????????????????v.equals("Java")).collect(Collectors.toList());
    System.out.println(flist);

    新寫法:

    var?flist?=?list.stream().filter(v?->
    ?????????????v.equals("Java")).collect(Collectors.toList());
    System.out.println(flist);

    2、優(yōu)點(diǎn)分析

    通過上面的示例我們可以看出, var 具備兩個(gè)明顯的優(yōu)點(diǎn):提高了代碼的可讀性和命名對(duì)齊。

    ① 提高了可讀性

    我們?cè)跊]有使用 var?之前,如果類型的名稱很長就會(huì)出現(xiàn)下面的這種情況:

    InternationalCustomerOrderProcessor>?orderProcessor?=?
    ????createInternationalOrderProcessor(customer,?order
    );

    當(dāng)限定每行不能超過 150 個(gè)字符的話,變量名就會(huì)被推到下一行顯示,這樣整個(gè)代碼的可讀性就變得很低。但當(dāng)我們使用了 var?之后,代碼就變成了這樣:

    var?orderProcessor?=?createInternationalOrderProcessor(customer,?order);

    從上述的代碼可以看出,當(dāng)類型越長時(shí),var(可讀性)的價(jià)值就越大。

    ② 命名對(duì)齊

    在不使用 var?時(shí),當(dāng)遇到下面這種情況,代碼就是這樣的:

    //?顯式類型
    No?no?=?new?No();
    AmountIncrease?more?=?new?BigDecimalAmountIncrease();
    HorizontalConnection?jumping?=
    ??new?HorizontalLinePositionConnection();
    Variable?variable?=?new?Constant(6);
    List?names?=?List.of("Java",?"哈哈哈");

    在使用了 var?之后,代碼是這樣的:

    var?no?=?new?No();
    var?more?=?new?BigDecimalAmountIncrease();
    var?jumping?=?new?HorizontalLinePositionConnection();
    var?variable?=?new?Constant(6);
    var?names?=?List.of("Java",?"哈哈哈");

    從上述代碼可以看出使用了 var?之后,命名對(duì)齊了,整個(gè)代碼也變得更優(yōu)雅了。

    3、使用規(guī)則 & 反例

    var?的實(shí)現(xiàn)來自于 JEP 286 (改善提議 286),詳情地址 :http://openjdk.java.net/jeps/286

    從 JEP 286 的標(biāo)題“局部變量類型推斷”可以看出,var?只能用于局部變量聲明,也就是說 var?必須滿足以下條件:

    • 它只能用于局部變量上;

    • 聲明時(shí)必須初始化;

    • 不能用作方法參數(shù)和全局變量(類變量)。

    PS:因?yàn)?var?的實(shí)現(xiàn)必須根據(jù)等會(huì)右邊的代碼進(jìn)行類型推斷,因此它不能被賦值 null 或不被初始化。

    反例一:未初始化和賦值 null

    反例二:中途類型更改


    反例三:全局變量

    反例四:作為返回值

    4、原理分析

    經(jīng)過前面的使用我們對(duì) var?已經(jīng)有了初步的認(rèn)識(shí),但 var?的實(shí)現(xiàn)原理是什么呢?

    為了搞清楚它的原理,我們對(duì)下面的代碼進(jìn)行了編譯(使用命令 javac MainTest.java):

    然后我們?cè)儆梅淳幾g工具打開被編譯的類發(fā)現(xiàn):var?竟然被替換成一個(gè)個(gè)確定的數(shù)據(jù)類型了,如下圖所示:

    由此我們可以得出結(jié)論:var?關(guān)鍵字的實(shí)現(xiàn)和它的名字密切相關(guān), var 只是局部類型推斷,它只會(huì)在 Java 編碼期和編譯期有效,當(dāng)類被編譯為 class 文件時(shí),var?就會(huì)變成一個(gè)個(gè)確定的數(shù)據(jù)類型(通過推斷得出)。 所以我們可以把 var 通俗的理解為 Java 的語法糖,使用它可以讓我們快速優(yōu)雅的實(shí)現(xiàn)業(yè)務(wù)代碼,但 var?在字節(jié)碼層面是不存在的。

    總結(jié)

    本文我們介紹了 var(局部類型推斷)的使用,它可以用在局部變量、 for、 Lambda?的變量聲明中,但不能用在全局變量的聲明中,也不能用它作為方法的返回值,并且在聲明時(shí)一定要進(jìn)行初始化(也不能賦值為 null)。使用 var?可以有效的提高代碼的可讀性和命名對(duì)齊,它的實(shí)現(xiàn)原理,是在編譯期通過等號(hào)右側(cè)的代碼進(jìn)行類型推斷,然后再將 var?替換成確定的數(shù)據(jù)類型。


    有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)

    歡迎大家關(guān)注Java之道公眾號(hào)


    好文章,我在看??

    瀏覽 35
    點(diǎn)贊
    評(píng)論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)
    評(píng)論
    圖片
    表情
    推薦
    點(diǎn)贊
    評(píng)論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

        • <dd id="5sdj3"></dd>
          <dfn id="5sdj3"></dfn>
        • <th id="5sdj3"></th>
          <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

          • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
          • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
            国产粗又大插美女视频 | 人妻在线无码 | 肏逼福利影城 | 国产视频3 | 日韩免费禁片 |