1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        快速了解 Java 9 - 16 新特性

        共 9335字,需瀏覽 19分鐘

         ·

        2021-06-12 05:49


        JAVA 這幾年的更新實(shí)在是太太太……快了,JAVA 8 都還沒(méi)用多久,16 都已經(jīng)發(fā)布了。自從 JAVA 8 發(fā)布了 Lambda  和 Stream 之后,JAVA 就像打了雞血一樣,半年一個(gè)版本的發(fā)布,生產(chǎn)隊(duì)的驢也沒(méi)這么勤快。

        導(dǎo)致我們現(xiàn)在完全跟不上 JAVA 發(fā)布的節(jié)奏,我司目前還停留在 JAVA 8,甚至部分老系統(tǒng)還在使用 JAVA 7,根本不能輕易的升級(jí)。

        不過(guò)雖然暫時(shí)用不上最新版本的 JAVA,但了解每個(gè)新版本的主要特性還是很重要的,不然哪天真跟著升級(jí)了,那還不得一臉懵逼。

        本文就帶你快速了解 JAVA 9 - 16 的主要新特性,早學(xué)完早下班!

        JAVA 9(2017年9月)

        接口里可以添加私有接口

        JAVA 8 對(duì)接口增加了默認(rèn)方法的支持,在 JAVA 9 中對(duì)該功能又來(lái)了一次升級(jí),現(xiàn)在可以在接口里定義私有方法,然后在默認(rèn)方法里調(diào)用接口的私有方法。

        這樣一來(lái),既可以重用私有方法里的代碼,又可以不公開(kāi)代碼

        public interface TestInterface {
            default void wrapMethod(){
                innerMethod();
            }
            private void innerMethod(){
                System.out.println("");
            }
        }

        匿名內(nèi)部類(lèi)也支持鉆石(diamond)運(yùn)算符

        JAVA 5 就引入了泛型(generic),到了 JAVA 7 開(kāi)始支持鉆石(diamond)運(yùn)算符:<>,可以自動(dòng)推斷泛型的類(lèi)型:

        List<Integer> numbers = new ArrayList<>();

        但是這個(gè)自動(dòng)推斷類(lèi)型的鉆石運(yùn)算符可不支持匿名內(nèi)部類(lèi),在 JAVA 9 中也對(duì)匿名內(nèi)部類(lèi)做了支持:

        List<Integer> numbers = new ArrayList<>() {
            ...
        }

        增強(qiáng)的 try-with-resources

        JAVA 7 中增加了try-with-resources的支持,可以自動(dòng)關(guān)閉資源:

        try (BufferedReader bufferReader = new BufferedReader(...)) {
            return bufferReader.readLine();
        }

        但需要聲明多個(gè)資源變量時(shí),代碼看著就有點(diǎn)惡心了,需要在 try 中寫(xiě)多個(gè)變量的創(chuàng)建過(guò)程:

        try (BufferedReader bufferReader0 = new BufferedReader(...);
            BufferedReader bufferReader1 = new BufferedReader(...)) {
            return bufferReader0.readLine();
        }

        JAVA 9 中對(duì)這個(gè)功能進(jìn)行了增強(qiáng),可以引用 try 代碼塊之外的變量來(lái)自動(dòng)關(guān)閉:

        BufferedReader bufferReader0 = new BufferedReader(...);
        BufferedReader bufferReader1 = new BufferedReader(...);
        try (bufferReader0; bufferReader1) {
            System.out.println(br1.readLine() + br2.readLine());
        }

        JAVA 10(2018年3月)

        局部變量的自動(dòng)類(lèi)型推斷(var)

        JAVA 10 帶來(lái)了一個(gè)很有意思的語(yǔ)法 - var,它可以自動(dòng)推斷局部變量的類(lèi)型,以后再也不用寫(xiě)類(lèi)型了,也不用靠 lombok 的 var注解增強(qiáng)了

        var message = "Hello, Java 10";

        不過(guò)這個(gè)只是語(yǔ)法糖,編譯后變量還是有類(lèi)型的,使用時(shí)還是考慮下可維護(hù)性的問(wèn)題,不然寫(xiě)多了可就成 JavaScript 風(fēng)格了

        JAVA 11(2018年9月)

        Lambda 中的自動(dòng)類(lèi)型推斷(var)

        JAVA 11 中對(duì) Lambda 語(yǔ)法也支持了 var 這個(gè)自動(dòng)類(lèi)型推斷的變量,通過(guò) var 變量還可以增加額外的注解:

        List<String> languages = Arrays.asList("Java""Groovy");
        String language = sampleList.stream()
          .map((@Nonnull var x) -> x.toUpperCase())
          .collect(Collectors.joining(", "));

        assertThat(language).isEqualTo("Java, Groovy");

        javac + java 命令一把梭

        以前編譯一個(gè) java 文件時(shí),需要先 javac 編譯為 class,然后再用 java 執(zhí)行,現(xiàn)在可以一把梭了:

        $ java HelloWorld.java
        Hello Java 11!

        Java Flight Recorder 登陸 OpenJDK

        Java Flight Recorder 是個(gè)灰常好用的調(diào)試診斷工具,不過(guò)之前是在 Oracle JDK 中,也跟著 JDK 11 開(kāi)源了,OpenJDK 這下也可以用這個(gè)功能,真香!

        JAVA 12(2019年3月)

        更簡(jiǎn)潔的 switch 語(yǔ)法

        在之前的 JAVA 版本中,switch語(yǔ)法還是比較啰嗦的,如果多個(gè)值走一個(gè)邏輯需要寫(xiě)多個(gè) case

        DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
        String typeOfDay = "";
        switch (dayOfWeek) {
            case MONDAY:
            case TUESDAY:
            case WEDNESDAY:
            case THURSDAY:
            case FRIDAY:
                typeOfDay = "Working Day";
                break;
            case SATURDAY:
            case SUNDAY:
                typeOfDay = "Day Off";
        }

        到了 JAVA 12,這個(gè)事情就變得很簡(jiǎn)單了,幾行搞定,而且!還支持返回值:

        typeOfDay = switch (dayOfWeek) {
            case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Working Day";
            case SATURDAY, SUNDAY -> "Day Off";
        };

        instanceof + 類(lèi)型強(qiáng)轉(zhuǎn)一步到位

        之前處理動(dòng)態(tài)類(lèi)型碰上要強(qiáng)轉(zhuǎn)時(shí),需要先 instanceof 判斷一下,然后再?gòu)?qiáng)轉(zhuǎn)為該類(lèi)型處理:

        Object obj = "Hello Java 12!";
        if (obj instanceof String) {
            String s = (String) obj;
            int length = s.length();
        }

        現(xiàn)在 instanceof 支持直接類(lèi)型轉(zhuǎn)換了,不需要再來(lái)一次額外的強(qiáng)轉(zhuǎn):

        Object obj = "Hello Java 12!";
        if (obj instanceof String str) {
            int length = str.length();
        }

        JAVA 13(2019年9月)

        switch 語(yǔ)法再增強(qiáng)

        JAVA 12 中雖然增強(qiáng)了 swtich 語(yǔ)法,但并不能在 -> 之后寫(xiě)復(fù)雜的邏輯,JAVA 12 帶來(lái)了 swtich更完美的體驗(yàn),就像 lambda 一樣,可以寫(xiě)邏輯,然后再返回:

        typeOfDay = switch (dayOfWeek) {
            case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {
                // do sth...
             yield "Working Day";
            }
            case SATURDAY, SUNDAY -> "Day Off";
        };

        文本塊(Text Block)的支持

        你是否還在為大段帶換行符的字符串報(bào)文所困擾,換行吧一堆換行符,不換行吧看著又難受:

        String json = "{\"id\":\"1697301681936888\",\"nickname\":\"空無(wú)\",\"homepage\":\"https://juejin.cn/user/1697301681936888\"}";

        JAVA 13 中幫你解決了這個(gè)惡心的問(wèn)題,增加了文本塊的支持,現(xiàn)在可以開(kāi)心的換行拼字符串了,就像用模板一樣:

        String json = """
            {
                "
        id":"1697301681936888",
                "
        nickname":"空無(wú)",
                "
        homepage":"https://juejin.cn/user/1697301681936888"
            }
            """;

        JAVA 14(2020年3月)

        新增的 record 類(lèi)型,干掉復(fù)雜的 POJO 類(lèi)

        一般我們創(chuàng)建一個(gè) POJO 類(lèi),需要定義屬性列表,構(gòu)造函數(shù),getter/setter,比較麻煩。JAVA 14 為我們帶來(lái)了一個(gè)便捷的創(chuàng)建類(lèi)的方式 - record

        public record UserDTO(String id,String nickname,String homepage) { };

        public static void main( String[] args ){
         UserDTO user = new UserDTO("1697301681936888","空無(wú)","https://juejin.cn/user/1697301681936888");
            System.out.println(user.id);
            System.out.println(user.nickname);
            System.out.println(user.id);
        }

        IDEA 也早已支持了這個(gè)功能,創(chuàng)建類(lèi)的時(shí)候直接就可以選:

        更直觀(guān)的 NullPointerException 提示

        NullPointerException 算是 JAVA 里最常見(jiàn)的一個(gè)異常了,但這玩意提示實(shí)在不友好,遇到一些長(zhǎng)一點(diǎn)的鏈?zhǔn)奖磉_(dá)式時(shí),沒(méi)辦法分辨到底是哪個(gè)對(duì)象為空。

        比如下面這個(gè)例子中,到底是 innerMap 為空呢,還是 effected 為空呢?

        Map<String,Map<String,Boolean>> wrapMap = new HashMap<>();
        wrapMap.put("innerMap",new HashMap<>());

        boolean effected = wrapMap.get("innerMap").get("effected");

        // StackTrace:
        Exception in thread "main" java.lang.NullPointerException
         at org.example.App.main(App.java:50)

        JAVA 14 也 get 到了 JAVAER 們的痛點(diǎn),優(yōu)化了 NullPointerException 的提示,讓你不在困惑,一眼就能定位到底“空”在哪!

        Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Boolean.booleanValue()" because the return value of "java.util.Map.get(Object)" is null
         at org.example.App.main(App.java:50)

        現(xiàn)在的 StackTrace 就很直觀(guān)了,直接告訴你 effected 變量為空,再也不用困惑!

        安全的堆外內(nèi)存讀寫(xiě)接口,別再玩 Unsafe 的騷操作了

        在之前的版本中,JAVA 如果想操作堆外內(nèi)存(DirectBuffer),還得 Unsafe 各種 copy/get/offset?,F(xiàn)在直接增加了一套安全的堆外內(nèi)存訪(fǎng)問(wèn)接口,可以輕松的訪(fǎng)問(wèn)堆外內(nèi)存,再也不用搞 Unsafe 的騷操作了。

        // 分配 200B 堆外內(nèi)存
        MemorySegment memorySegment = MemorySegment.allocateNative(200);

        // 用 ByteBuffer 分配,然后包裝為 MemorySegment
        MemorySegment memorySegment = MemorySegment.ofByteBuffer(ByteBuffer.allocateDirect(200));

        // MMAP 當(dāng)然也可以
        MemorySegment memorySegment = MemorySegment.mapFromPath(
          Path.of("/tmp/memory.txt"), 200, FileChannel.MapMode.READ_WRITE);

        // 獲取堆外內(nèi)存地址
        MemoryAddress address = MemorySegment.allocateNative(100).baseAddress();

        // 組合拳,堆外分配,堆外賦值
        long value = 10;
        MemoryAddress memoryAddress = MemorySegment.allocateNative(8).baseAddress();
        // 獲取句柄
        VarHandle varHandle = MemoryHandles.varHandle(long.classByteOrder.nativeOrder());
        varHandle.set(memoryAddress, value);

        // 釋放就這么簡(jiǎn)單,想想 DirectByteBuffer 的釋放……多奇怪
        memorySegment.close();

        新增的 jpackage 打包工具,直接打包二進(jìn)制程序,再也不用裝 JRE 了

        之前如果想構(gòu)建一個(gè)可執(zhí)行的程序,還需要借助三方工具,將 JRE 一起打包,或者讓客戶(hù)電腦也裝一個(gè) JRE 才可以運(yùn)行我們的 JAVA 程序。

        現(xiàn)在 JAVA 直接內(nèi)置了 jpackage 打包工具,幫助你一鍵打包二進(jìn)制程序包,終于不用亂折騰了

        JAVA 15(2020年9月)

        ZGC 和 Shenandoah 兩款垃圾回收器正式登陸

        在 JAVA 15中,ZGC 和 Shenandoah 再也不是實(shí)驗(yàn)功能,正式登陸了(不過(guò) G1 仍然是默認(rèn)的)。如果你升級(jí)到 JAVA 15 以后的版本,就趕快試試吧,性能更強(qiáng),延遲更低

        封閉(Sealed )類(lèi)

        JAVA 的繼承目前只能選擇允許繼承和不允許繼承(final 修飾),現(xiàn)在新增了一個(gè)封閉(Sealed )類(lèi)的特性,可以指定某些類(lèi)才可以繼承:

        public sealed interface Service permits CarTruck {

            int getMaxServiceIntervalInMonths();

            default int getMaxDistanceBetweenServicesInKilometers() {
                return 100000;
            }

        }

        JAVA 16(2021年3月)

        JAVA 16 在用戶(hù)可見(jiàn)的地方變化并不多,基本都是 14/15 的實(shí)驗(yàn)性?xún)?nèi)容,到了 16 正式發(fā)布,這里就不重復(fù)介紹了。

        總結(jié)

        以上介紹的各種新特性,有些特性在歷史版本中還屬于實(shí)驗(yàn)性功能,不過(guò)按照 JAVA 目前這個(gè)驢一樣的更新頻率,很可能下個(gè)版本就是穩(wěn)定版了。早學(xué)早享受,晚學(xué)被卷走……

        來(lái)源:juejin.cn/post/6964543834747322405


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

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            黄色电影一级大片 | 国产好爽…又高潮了毛片 | 国产精品久久久久毛片软件 | 欧美人妻黑人精品久久五月天婷婷 | 操你逼视频| 小莹浴室激情2 | 他扒开我的内裤把舌头进去动态图 | free艳丽少妇pics | 潘金莲西门庆一级淫片aaaaaa | chinese麻豆 |