Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Java 15の新機能 Recordsを中心に / New feature in Java 15 around the Records

Naoki Kishida
September 28, 2020

Java 15の新機能 Recordsを中心に / New feature in Java 15 around the Records

2020/9/28に開催されたJJUGナイトセミナーでの登壇資料です
https://jjug.doorkeeper.jp/events/111440

Naoki Kishida

September 28, 2020
Tweet

More Decks by Naoki Kishida

Other Decks in Programming

Transcript

  1. Java 15で変更された言語機能 • Records(Second Preview) • Pattern Matching for instanceof(Second

    Preview) • 変更なし • Sealed Classes(Preview) • Text Blocks(Standard) • 変更なし
  2. Preview機能 • 言語機能の試用版 • 基本的にpreview, second previewの2回のpreviewを経て正式 化する • 正式化までに3バージョン必要

    • 明確な決まりがあるわけではない • javacやjavaコマンドなどで`--enable-preview`が必要 • `-source`でのバージョン指定も必要
  3. Recordの定義 public record Rec(String name, int count) {} public final

    class Rec extends Record { private final String name; private final int count; Rec(String name, int count) { this.name = name; this.count = count; } String name() { return name; } String count() { return count; } // toString, equals, hashCode } 中かっこが必要 いろいろな定義も可 要素(コンポーネント)を定義 recordで宣言 コンポーネントに 対応するフィールド private final java.lang.Recordを継承 暗黙にfinal コンストラクタが定義される コンポーネントと同名の アクセスメソッド not getter オブジェクトの基本メソッドも 実装される
  4. コンパクトコンストラクタ • 必ず書かないといけないものは省略していいのでは? record Rec(String name, int count) { Rec(String

    name, int count) { this.name = name; this.count = Math.max(count, 0); } } record Rec(String name, int count) { Rec { count = Math.max(count, 0); } } フィールド初期化が必須 パラメータを省略 フィールド初期化 してはいけない
  5. Pattern Matching for instanceof(2nd Preview) • Kotlinのスマートキャストのような機能 Object o =

    "test"; if (o instanceof String s) { System.out.println(s.length()); } Object o = "test"; if (o instanceof String) { String s = (String) o; System.out.println(s.length()); }
  6. 現状では使い道なし • 本当は次のように書けるといい • Pattern matching for switchなどが来れば便利に(後半に説明) String getName(Shape

    s) { if (s instanceof Circle) { return "円"; } else if (s instanceof Rectangle) { return "四角"; } else if (s instanceof Square) { return "正方形"; } }
  7. Sealed Classesの階層 • Sealed Classを継承する場合、sealed・final・non-sealedの いずれかが必要 • recordは暗黙的にfinal Hoge Foo

    Bar Baz sealed 要 sealed 要 final or non-sealed 要 final or non-sealed MyBaz Bazがnon-sealedであれば 継承できる。sealされない sealed class Hoge permits Foo, Bar {} final class Foo extends Hoge {} sealed class Bar extends Hoge permits Baz {} non-sealed class Baz extends Bar {} class MyBaz extends Baz {}
  8. Switch式のおさらい • Switchがステートメントとしてだけではなく式として使える • Java 14で標準化 int numLetters = switch

    (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; }
  9. 複数のcaseラベル • case句に複数のラベルを指定できるようになった switch (day) { case MONDAY: case FRIDAY:

    case SUNDAY: numLetters = 6; break; case TUESDAY: numLetters = 7; break; case THURSDAY: case SATURDAY: numLetters = 8; break; case WEDNESDAY: numLetters = 9; break; }; switch (day) { case MONDAY, FRIDAY, SUNDAY: numLetters = 6; break; case TUESDAY: numLetters = 7; break; case THURSDAY, SATURDAY: numLetters = 8; break; case WEDNESDAY: numLetters = 9; break; };
  10. アロー形式 • ラムダ式のようなアロー(->)が使える • わずらわしい`break`が不要 switch (day) { case MONDAY,

    FRIDAY, SUNDAY: numLetters = 6; break; case TUESDAY: numLetters = 7; break; case THURSDAY, SATURDAY: numLetters = 8; break; case WEDNESDAY: numLetters = 9; break; }; switch (day) { case MONDAY, FRIDAY, SUNDAY -> numLetters = 6; case TUESDAY -> numLetters = 7; case THURSDAY, SATURDAY -> numLetters = 8; case WEDNESDAY -> numLetters = 9; };
  11. 式 switch (day) { case MONDAY, FRIDAY, SUNDAY -> numLetters

    = 6; case TUESDAY -> numLetters = 7; case THURSDAY, SATURDAY -> numLetters = 8; case WEDNESDAY -> numLetters = 9; }; numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; };
  12. swtichでパターンマッチングが使えるように なると便利 • Pattern matching for switchが導入されてSealed classを使う と、次のようなswitchがdefaultなしで書けるようになる String

    getName(Shape s) { return switch (s) { case Circle c -> return "円"; case Rectangle r -> return "四角"; case Square q -> return "正方形"; } }
  13. Deconstruction • 脱構築? • ジャック・デリダ • 静的な構造を前提とする→構造を分解して新しい構造を構築する • パターンマッチングで構造を分解する record

    Point(int x, int y) {} int getLen(Point p) { return switch (p) { case Point(0, int y) -> y; case Point(int x, 0) -> x; case Point(int x, int y) -> (int)sqrt(x * x + y * y); } }
  14. ScalaのOptionのパターンマッチング • ScalaではOptionがsealed classになっていてパターンマッチン グが使える sealed class Option[A] case class

    Some[A](x: A) extends Option[A] case object None extends Option[Nothing] def a(opt: Option[String]):String = { opt match { case Some(s) => "message is %s" format s case None => "empty message" } } ※ コードはイメージです 定義 利用
  15. つまりSealed Classesは • Deconstructionでは親クラス・子クラスを公開する 必要がある • その上でユーザーに継承させないという制限ができなかった • final or

    not • だれにも継承できないか、だれでも継承できる • Sealed Classによって継承を制限できる • 安心してDeconstructionを前提にしたクラス構造が設計できる