6. 2023 State of Java Ecosystem
• New Relic first published in March 2020
• 2023 state was published in April 2023
• Based on data gathered from millions of
applications providing performance data
• The data for this report was drawn entirely
from applications reporting to New Relic in
January 2023 and does not provide a global
picture of Java usage.
6
Source: https://newrelic.com/resources/report/2023-state-of-java-ecosystem
16. Pattern Matching for switch
String text = switch (obj) {
case null -> "NULL"; // null check
case String s -> "String: " + s;
case Integer i
when i < 10_000 -> "Small Int: " + i;
case Integer i -> "Big Int: " + i;
case Long l -> "Long: " + l;
case Number n -> "Number: " + n;
default -> "Object: " + obj;
}
16
1. 可以檢查 null
2. 可以用 when 來增加判斷式
(guarded pattern)
3. Java14 讓 switch 可以回
傳值並設定 text 變數內容
17. 注意!上下順序很重要!
String text = switch (obj) {
case null -> "NULL";
case String s -> "String: " + s;
case Number n -> "Number: " + n;
// Error: this case label is dominated
// by a preceding case label
case Integer i -> "Integer: " + i; // unreachable
case Long l -> "Long: " + l;
default -> "Object: " + obj;
}
17
到不了的地方叫遠方
18. 支配權 Dominance
• 父類別大於子類別 (例:Number > Integer)
• Unguarded pattern 大於 guarded pattern
(case Type > case Type when expr.)
• Guarded pattern when true 大於其他
pattern(guarded & unguarded)
• Pattern 大於常數(Integer i > 1, 2)
• Enum 類別大於常數(Color > Color.RED)
• when 不會進行過多的額外檢查
18
19. 建議撰寫原則
• 先寫 case null (純粹為了易讀性與維護性)
• 次寫 case 常數和列舉常數
• 再寫 guarded 的 case Type t when 判斷式
• 後寫 unguarded 的 case Type t
• 特別注意 Type 的子類別要放在父類別之前
• 最後寫 default 做收尾(若未窮舉的話)
19
20. 搭配 enum 一起用
enum Color { RED, GREEN, BLUE, YELLOW, PURPLE }
String text = switch (obj) {
case null -> "NULL";
case Color.BLUE -> "Color.BLUE"; // 短版本
case Color c
when c == Color.RED -> "Color.RED";// 與上式等價
case Color c -> "Color: others"; // 注意支配性
case int[] ia -> "Int array: " + ia; // 陣列也可以
default -> "Object: " + obj;
}
20
記得 enum、sealed 需要注
意是否要窮舉所有可能值!
22. class Point { // immutable
private final int x, y;
public Point(int x, int y) { this.x=x; this.y=y; }
public int x() { return x; }
public int y() { return y; }
public boolean equals(Object o) {
return o instanceof Point
&& ((Point) o).x == x
&& ((Point) o).y == y;
}
public int hashCode() { return Objects.hash(x, y); }
public String toString() {
return String.format("Point[x=%d, y=%d]", x, y);
}
}
回到 Java 上古時代(= Java 7)
22
23. Java16 record + Java17 sealed
23
record Point(int x, int y) {} // 上頁的程式碼濃縮成一行了
// 順便增加一些複雜度
sealed interface Shape
permits Circle, Rectangle, Triangle {
public static void check(Point p) {
if (p.x() <= 0)
throw new IllegalArgumentException("NG!");
}
}
record Circle(Point p, int r, Color c)
implements Shape {}
record Rectangle(Point p1, Point p2, Color c)
implements Shape {}
record Triangle(Point p1, Point p2, Point p3, Color c)
implements Shape {}
24. return switch (obj) {
case null -> "NULL";
case Point p -> "Point: " + p; // Pattern matching
case Circle(Point p, int r, Color c) // record pattern
-> "Circle: p:" + p;
case Rectangle(Point p1, Point p2, Color c)
-> "Rectangle: 1:" + p1 + ", 2:" + p2;
case Triangle(Point p1, Point p2, Point p3, Color c)
-> "Triangle: 1:" + p1 + ", 2:" + p2 + ", 3:" + p3;
default -> "Object: " + obj;
};
24
這樣一來就不需要使用
case Circle c -> c.p();
Record Pattern
25. record Pair<T>(T a, T b) {}
private Pair<Shape> o;
switch (o) {
// 要窮舉所有可能值
case Pair<Shape>(Circle c, Shape s) -> ...
case Pair<Shape>(Rectangle r, Circle c) -> ...
case Pair<Shape>(Rectangle r, Rectangle r) -> ...
case Pair<Shape>(Rectangle r, Triangle t) -> ...
case Pair<Shape>(Triangle t, Shape s) -> ...
// 或是用下列任一行收尾
case Pair<Shape>(var a, var b) -> ...
case Pair<Shape> x -> ...
default -> ...
}
25
要注意是否已窮舉
26. If record in if
// Java 16 ~ 20
if (o instanceof Point p) {
int x = p.x();
int y = p.y();
System.out.println(x + y);
}
// Java 21 Record pattern
if (o instanceof Point(int x, int y)) {
System.out.println(x + y);
}
26
27. 更複雜的 Record Pattern
if (o instanceof Circle(Point(int x, int y), int r, Color c)) {
System.out.println(x + y);
}
if (o instanceof Rectangle(Point(var x,var y), var p2, var c)) {
System.out.println(x); // 也可以使用 var
}
if (o instanceof Triangle(Point(int x1, int y1),
Point(var x2, var y2), Point p3, var c)) {
System.out.println(c);
}
27
程式碼能夠
簡化嗎?
28. Unnamed Patterns (Preview)
if (o instanceof Circle(Point(int x, int y), int _, Color _) {
System.out.println(x + y); // unnamed pattern variable
}
if (o instanceof Rectangle(Point(var x, _), _, _) {
System.out.println(x); // unnamed pattern (Type v)
}
if (o instanceof Triangle(_, _, _, var c) { // unnamed pattern
System.out.println(c);
}
if (o instanceof Point _) { // unnamed pattern variable
System.out.println("Point!");
}
28
程式碼複雜度降
低,可讀性增加!
29. Unnamed Variables (Preview)
var points = new ArrayList<Point>(List.of(p1, p2, p3, p4, p5));
for (Point _ : points) { // enhanced for loop
if (DEBUG) count++;
}
for (int i = 0, _ = init(); i < count; i++) { // for statement
try (var _ = getRes()) { // try-with-resources statement
Point p = points.getFirst();
Shape.check(p);
m.putAll(Arrays.stream(Color.values())
.map(c -> new Circle(p, i, c))
.collect(toMap(Function.identity(),
_ -> 1L)) //lambda
);
} catch (IllegalArgumentException _) { // exception
var _ = points.removeFirst(); // local variable
}
}
29
30. 這是禁止事項 🙅
• o instanceof _
• o instanceof _(int x, int y)
• o instanceof var _
• case _
• case var _
• case Type(_)
• void test(String x, int _) {}
• ...
30
32. 各自表述,沒有共識
First element Last element
List list.get(0) list.get(list.size() - 1)
Deque deque.getFirst() deque.getLast()
SortedSet set.first() set.last()
LinkedHashSet set.iterator().next() // missing
32
不同集合取得
首尾元素有不
同做法……
35. SequencedCollection
// new method
SequencedCollection<E> reversed();
// methods promoted from Deque
void addFirst(E);
void addLast(E);
E getFirst();
E getLast();
E removeFirst();
E removeLast();
// add*(E) & remove*() are optional (unmodifiable)
// get*() & remove*() throw NoSuchElementEx if empty
35
50. Core Java Library
• JEP 431: Sequenced Collections
• JEP 442: Foreign Function & Memory API
(Third Preview)
• JEP 444: Virtual Threads
• JEP 446: Scoped Values (Preview)
• JEP 448: Vector API (Sixth Incubator)
• JEP 453: Structured Concurrency (Preview)
50
51. Java Language Specification
• JEP 430: String Templates (Preview)
• JEP 440: Record Patterns
• JEP 441: Pattern Matching for switch
• JEP 443: Unnamed Patterns and Variables
(Preview)
• JEP 445: Unnamed Classes and Instance
Main Methods (Preview)
51
52. HotSpot & Security
• JEP 439: Generational ZGC
• JEP 449: Deprecate the Windows 32-bit x86
Port for Removal
• JEP 451: Prepare to Disallow the Dynamic
Loading of Agents
• JEP 452: Key Encapsulation Mechanism API
• NOTE THAT JEP 404, Generational
Shenandoah (Experimental), originally
targeted for 21, was officially removed
52