Slide 1

Slide 1 text

Java 15の新機能 Recordsを中心に LINE Fukuoka きしだ なおき 2020/9/28 JJUG ナイトセミナー

Slide 2

Slide 2 text

自己紹介 • きしだ なおき(@kis) • LINE Fukuoka • 最近 洗濯機がある生活をはじめて パンツは4枚くらいあれば回せるんだなと気づく

Slide 3

Slide 3 text

Java 15で変更された言語機能 • Records(Second Preview) • Pattern Matching for instanceof(Second Preview) • 変更なし • Sealed Classes(Preview) • Text Blocks(Standard) • 変更なし

Slide 4

Slide 4 text

Preview機能 • 言語機能の試用版 • 基本的にpreview, second previewの2回のpreviewを経て正式 化する • 正式化までに3バージョン必要 • 明確な決まりがあるわけではない • javacやjavaコマンドなどで`--enable-preview`が必要 • `-source`でのバージョン指定も必要

Slide 5

Slide 5 text

Records(2nd Preview) • データをやりとりするための型 • イミュータブル(値が変更できない) • 名前付きタプル • Case class(Scala) やData class(Kotlin), @Value(Lombok)

Slide 6

Slide 6 text

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 オブジェクトの基本メソッドも 実装される

Slide 7

Slide 7 text

Recordの利用 • 利用時は普通のクラスと同様 Rec r = new Rec("Java", 15);

Slide 8

Slide 8 text

カノニカルコンストラクタ • コンストラクタの定義では、引数にコンポーネントをその型で その順番で、そしてそれだけを書く必要がある • コンポーネントに対応する内部フィールドを必ず初期化しない といけない • カノニカル(正規)コンストラクタ

Slide 9

Slide 9 text

コンパクトコンストラクタ • 必ず書かないといけないものは省略していいのでは? 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); } } フィールド初期化が必須 パラメータを省略 フィールド初期化 してはいけない

Slide 10

Slide 10 text

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()); }

Slide 11

Slide 11 text

Sealed Classes • 継承できるクラスを限定する • shield(盾) classではなくてsealed(密閉された) class public abstract sealed class Shape permits Circle, Rectangle, Square {...}

Slide 12

Slide 12 text

( ´∀`)<シールドクラス • 公式にはシール・クラス?

Slide 13

Slide 13 text

現状では使い道なし • 本当は次のように書けるといい • 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 "正方形"; } }

Slide 14

Slide 14 text

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 {}

Slide 15

Slide 15 text

non-sealed • ハイフン入りキーワード! • 実際はキーワードではない • switch式のときにbreak-withが検討されていた • package-privateなども可能

Slide 16

Slide 16 text

Sealed Classedはなんのため? • パターンマッチングが完成したときに必要 • いまは途中経過

Slide 17

Slide 17 text

今後の計画 • Pattern Matching for switch • Deconstruction

Slide 18

Slide 18 text

Pattern Matching for switch • パターンマッチングをswitch式/文で使えるようにする

Slide 19

Slide 19 text

Switch式のおさらい • Switchがステートメントとしてだけではなく式として使える • Java 14で標準化 int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; }

Slide 20

Slide 20 text

複数の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; };

Slide 21

Slide 21 text

アロー形式 • ラムダ式のようなアロー(->)が使える • わずらわしい`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; };

Slide 22

Slide 22 text

式 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; };

Slide 23

Slide 23 text

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 "正方形"; } }

Slide 24

Slide 24 text

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); } }

Slide 25

Slide 25 text

これでなにがしたいの? • Optionalをパターンマッチングしたい

Slide 26

Slide 26 text

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" } } ※ コードはイメージです 定義 利用

Slide 27

Slide 27 text

必要な構造 • Optionalがinterfaceになる必要がある・・・ • リフレクションで非互換性がでる • Sealed Classesがない場合は自由にimplementできてしまうの でfinal classになっていた Optional Some None

Slide 28

Slide 28 text

Optionalのパターンマッチング • こんなコードが書けるとうれしい String foo(Optional opt) { return switch(opt) { Some(var s) -> "message is %s".formatted(s); None -> "empty message"; }; }

Slide 29

Slide 29 text

つまりSealed Classesは • Deconstructionでは親クラス・子クラスを公開する 必要がある • その上でユーザーに継承させないという制限ができなかった • final or not • だれにも継承できないか、だれでも継承できる • Sealed Classによって継承を制限できる • 安心してDeconstructionを前提にしたクラス構造が設計できる

Slide 30

Slide 30 text

まとめ • 「使える」パターンマッチングの導入が最終目標 • 機能をうまく分解して導入している • 全部そろったときにあわてないよう予習しておきましょう