五個Java冠軍喜歡的Java 16強大功能 - oracle

發表於2021-06-09

Java Magazine 聯絡了幾位 Java Champion,即來自 Java 社群各個領域的技術傑出人物,問題很簡單:“ JDK 16中什麼是最重要的部分?”

 

1. JEP 395(記錄)

作者:Ivar Grimstad,Java 冠軍

對我來說,JDK 16 中最重要的特性是JEP 395: Records,它減少了所需的樣板程式碼量。從未寫過的程式碼是最好的程式碼,因為它保證不包含任何錯誤!

一段record Point(int x, int y) { }可以替代下面整個程式碼:

class Point {
    private final int x;
    private final int y;

    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    int x() { return x; }
    int y() { return y; }

    public boolean equals(Object o) {
        if (!(o instanceof Point)) return false;
        Point other = (Point) o;
        return other.x == x && other.y = y;
    }

    public int hashCode() {
        return Objects.hash(x, y);
    }

    public String toString() {
        return String.format("Point[x=%d, y=%d]", x, y);
    }
}

 

2. JEP 394(instanceof 的模式匹配)

作為一名開發人員,我對jep394的當前功能和用法感到興奮:java16中instanceof的模式匹配,以及它如何擴充套件到其他語言結構,如switch表示式和未來Java版本中的其他語言結構。而且,這個特性可以在日常程式碼中經常使用,這使得它更加有用。

在其當前用法中,此功能將模式匹配應用於instanceof運算子,並可以消除以下程式碼中明顯重複的compareUsingInstanceof ifTrue cast:

void outputValueInUppercase(Object obj) {
    if (obj instanceof String) { 
        String s = (String) obj; 
        System.out.println(s.toUpperCase()); 
    }
}

它還可以通過引入模式變數(如str)簡化程式碼,如下所示:

void outputValueInUppercase(Object obj) {
    if (obj instanceof String str) { 
        System.out.println(str.toUpperCase()); 
    }
}

instanceof的模式匹配的簡單性可能具有欺騙性。下面是一個示例,說明開發人員通常如何使用兩個例項變數model(字串值)和price(雙倍值)重寫類(在本例中為Monitor)的equals()方法:

public class Monitor {
   String model;
   double price;
   @Override
   public boolean equals(Object o) {
       if (o instanceof Monitor) {
           Monitor other = (Monitor) o;
           if (model.equals(other.model) && price == other.price) {
               return true;
           }
       }
       return false;
   }
}

下面是如何通過使用instanceof的模式匹配和if語句的進一步簡化來簡化前面的equals()方法:

public boolean equals(Object o) {
    return o instanceof Monitor other 
        && model.equals(other.model) && price == other.price;
}

這只是冰山一角。作為一個開發人員,您可以使用instanceof的模式匹配來簡化您的程式碼,這在以前是不可行的。例如,以下程式碼

void processChildNode(Tree tree) {
        if (tree.getChildNodes() instanceof Map) {
            Map<?, Node> childNodes = (Map<?, Node>) tree.getChildNodes();
            if (childNodes.size() == 1) {
                Node node = childNodes.get("root");
                if (node instanceof LetterNode) {
                    LetterNode letterNode = (LetterNode) node;
                    letterNode.isLatin();
                }
            }
        }
    }

簡化為:

void processChildNode(Tree tree) {
        if (tree.getChildNodes() instanceof Map<?, Node> childNodes 
            && childNodes.size() == 1 
            && childNodes.get("root") instanceof LetterNode letterNode) {
                letterNode.isLatin();
        }
    }

生成的程式碼更易於閱讀和理解,簡潔,並且應該更易於維護。我迫不及待地想看看這個特性將來如何應用到其他語言結構中。

 

3.JEP 394(instanceof 的模式匹配)

作者:Arjan Tijms,Java 冠軍

雖然 JDK 16 中有很多非常有趣的東西,但對我來說,亮點是用於instanceof檢查時模式匹配的初始版本,它通常非常嘈雜並且容易出錯。

在 JEP 394 之前:

if (asyncStartRequest instanceof HttpServletRequest) {
     HttpServletRequest httpServletRequest = (HttpServletRequest) 
         asyncStartRequest;
     path = httpServletRequest
                .getRequestURI()
                .substring(httpServletRequest.getContextPath().length());
  } else {
      path = …
  }

JEP 394 之後:

if (asyncStartRequest instanceof HttpServletRequest httpServletRequest) {
      path = httpServletRequest
                .getRequestURI()
                .substring(httpServletRequest.getContextPath().length());
  } else {
      path = …
  }

if塊的嘈雜的第一行現在消失了,您可以立即關注路徑分配。您也不會意外地檢查ServletRequest並將其轉換為HttpServletRequest。

這個新特性非常有趣,因為它將是Java中首次引入模式匹配。

 

4. Stream.toList()

作者:Java Champion Tagir Valeev

自從在 Java 8 中引入Stream以來,Stream API 就因其冗長而受到指責。例如,對列表執行簡單的對映轉換需要儘可能多地編寫list.stream().map(fn).collect(toList());使用新版本,您現在可以編寫更短、更清晰的程式碼,例如list.stream().map(fn).toList(). (沒有了collect)

首先,雖然規範不能保證這一點,但是collect(toList())產生了一個可變列表,許多使用者已經依賴這個事實。新方法Stream.toList()生成一個不可修改的列表。它也不是collect(toUnmodifiableList())的快捷方式,因為toUnmodifiableList()不接受空值。

其次,Stream.toList()的實現不受collect介面的約束。

因此,Stream.toList()更優化,分配的記憶體更少,特別是在預先知道流大小的情況下。

5. JEP 338(向量 API)、JEP 389(外部連結器 API)和 JEP 393(外部記憶體訪問 API)

作者Rafael Winterhalter,Java 冠軍

Java 16 彌補了更多差距,以更好地與執行 JVM 的硬體配合使用。

使用孵化向量 API (JEP 338),JVM 開發人員可以開始探索如何改進程式碼的執行時,其中向量化有時可以實現很大的改進。

藉助孵化外部連結器 API (JEP 389),開發人員還可以更輕鬆地包含本機程式碼。

孵化中的外部記憶體訪問 API (JEP 393)最終允許從 Java 進行適當的直接記憶體操作。

所有這些變化使我們更接近於更好地將 JVM 庫和應用程式與硬體整合,而不依賴於不安全的內部 API,一旦時間準備好並且這些 API 最終確定,這將使 JVM 成為一個更安全、更可靠的平臺。未來版本。

我非常期待嘗試這些孵化 API,它們共同為 Java 的未來開啟了一扇大門。

相關文章