2025年10月29日 星期三

Java 21新特性Record Pattern與Switch Pattern 文/恆逸資深講師 張益裕




Oracle於2023年9月發布Java 21,是在Java 17之後的長期支援 (LTS) 版本,接下來討論Java 21加入的新特性Record Pattern與Switch Pattern。

Java 14加入新的類型record,如果需要一個可以簡單封裝資料的型態,而且封裝的資料不需要更改,record會是比一般類別更好的選擇:

  // 宣告record類別, 封裝兩個變數
  public record Point(int x, int y) { }

宣告好的record可以用來建立物件與呼叫自動加入的方法:

  // 宣告與建立 Point 物件
  Point p = new Point(3, 5);
  Point p2 = new Point(3, 5);

  // 只能呼叫與變數同樣名稱的方法取得變數值
  System.out.printf( "Point: x: %d, y: %d%n", p.x(), p.y() );

  // 自動加入的 toString, equals與hashCode方法
  System.out.printf( "p.toString(): %s%n", p.toString() );
  System.out.printf( "p.equals(p2): %s%n", p.equals(p2) );
  System.out.printf( "p.hashCode(): %d%n", p.hashCode() );

Record類別也可以實作介面:

  interface Shape {}
  record Circle(double radius) implements Shape { }
  record Square(double side) implements Shape { }
  record Rectangle(double length, double width) implements Shape { }

傳統的做法使用instanceof判斷物件的種類:

  Shape shape = new Circle(10);
  double area = 0.0;

  // 計算圓形面積
  if (shape instanceof Circle) {
      Circle c = (Circle)shape;
      area = Math.PI * c.radius() * c.radius();
  }
  // 計算方形面積
  else if (shape instanceof Square) {
      Square s = (Square)shape;
      area = s.side() * s.side();
  }
  // 計算圓矩形面積
  else if (shape instanceof Rectangle) {
      Rectangle r = (Rectangle)shape;
      area = r.length() * r.width();
  }

Java 16加入instanceof pattern matching,可以省掉冗長的轉型:

  Shape shape = new Circle(10);
  double area = 0.0;

  // 計算圓形面積
  if (shape instanceof Circle c) {
      area = Math.PI * c.radius() * c.radius();
  }
  // 計算方形面積
  else if (shape instanceof Square s) {
      area = s.side() * s.side();
  }
  // 計算圓矩形面積
  else if (shape instanceof Rectangle r) {
      area = r.length() * r.width();
  }

Java 21加入的record pattern可以讓這類的工作更加清楚與簡短:

  Shape shape = new Circle(10);
  double area = 0.0;

  // 計算圓形面積
  if (shape instanceof Circle(double radius)) {
      area = Math.PI * radius * radius;
  }
  // 計算方形面積
  else if (shape instanceof Square(double side)) {
      area = side * side;
  }
  // 計算圓矩形面積
  else if (shape instanceof Rectangle(double length, double width)) {
      area = length * width;
  }

使用if與instanceof搭配的判斷,可以執行好這類的工作,不過程式碼看起來會感覺比較複雜一些,這種判斷的工作其實更適合使用switch,尤其是使用在Java 14加入的switch expression,程式碼會更加清楚與簡短:

  double area = switch (shape) {
      // 計算圓形面積
      case Circle c -> Math.PI * c.radius() * c.radius();
      // 計算方形面積
      case Square s ->  s.side() * s.side();
      // 計算圓矩形面積
      case Rectangle r -> r.length() * r.width();
      default -> 0.0;
  };

Java 21為switch加入新的Pattern Matching語法:

  double area = switch(shape) {
      // 計算圓形面積
      case Circle(double radius) -> Math.PI * radius * radius;
      // 計算方形面積
      case Square(double side) -> side * side;
      // 計算圓矩形面積
      case Rectangle(double length, double width) -> length * width;
      default -> 0.0;
  };

經過幾種不同寫法比較之後,可以發現結合幾個Java版本提供新特性,最後採用record pattern與switch pattern matching,可以讓這類的工作使用最清楚與簡短的程式碼完成需要的工作。


您可在下列課程中了解更多技巧喔!

0 意見:

張貼留言