Slide 1

Slide 1 text

JEP 482 Flexible Constructor Bodies (Second Preview) しおつき ( @tsukiotsuki_ ) 1

Slide 2

Slide 2 text

自己紹介 しおつき ( @tsukiotsuki_ ) スミセイ情報システム株式会社 製品開発チームの技術・後輩フ ォロー、ド派手何でも屋 エンジニア歴  11年 趣味:ゲーム ・ダイビング 2

Slide 3

Slide 3 text

目的 Javaのコンストラクタに関する従来の制約を緩和し、より柔軟で表現力豊かなコード が書けるようにすること JEP447 Flexible Constructor Bodies (Second Preview) を名前変更して、第2プレビ ューとして機能追加 : Java22でリリース済み JEP482の変更点 コンストラクタ本体が、コンストラクタを明示的に呼び出す前に、同じクラス内のフ ィールドを初期化できるようにする。 3

Slide 4

Slide 4 text

JEP447の変更内容 親クラスのコンストラクタ呼び出し前に、処理を書けるようになった。 制約: 生成(初期化)前のインスタンスを参照しない処理のみに限る。 (未初期化の フィールドアクセスの禁止) コンストラクタのトップダウンの実行順序の維持し、サブクラスのコンストラ クタがスーパークラスの初期化に干渉しない。 4

Slide 5

Slide 5 text

sample class Base { Base(int x) { System.out.println("Base constructor: " + x); } } class Derived extends Base { int y; Derived(int x, int y) { System.out.println("Setting y"); super(x); // superの前にインスタンスに関与しないステートメントを配置 this.y = y; } } 5

Slide 6

Slide 6 text

JEP482の変更内容 コンストラクタ本体が、コンストラクタを明示的に呼び出す前に、同じクラス内 のフィールドを初期化できるようにする。 制約: フィールドの初期化は行えるが、フィールドの読み取りはできない。 生成(初期化)前のインスタンスを参照しない処理のみに限る。 (未初期化の フィールドアクセスの禁止) 6

Slide 7

Slide 7 text

sample class Base { Base(int x) { System.out.println("Base constructor: " + x); } } class Derived extends Base { int y; Derived(int x, int y) { this.y = y; // フィールドの初期化をsuperの前に配置可能 System.out.println("Derived constructor: " + y); super(x); } } 7

Slide 8

Slide 8 text

利用例 1 : スーパークラスのコンストラクタ引数の検証 < Beforeパターン1:初期化後に検証する> public class Sub extends Super { public Sub(long value) { super(value); // 制約による親クラスの呼び出し if (value <= 0) throw new IllegalArgumentException("not allowed value"); } } 8

Slide 9

Slide 9 text

< Beforeパターン2:スーパークラスのコンストラクタ呼び出し前に検証する> public class Sub extends Super { public Sub(long value) { super(verifyValue(value)); } private static long verifyValue(long value) { if (value <= 0) throw new IllegalArgumentException("not allowed value"); return value; } } 9

Slide 10

Slide 10 text

<適用後> public class Sub extends Super { public Sub(long value) { if (value <= 0) throw new IllegalArgumentException("not allowed value"); super(value); } } 10

Slide 11

Slide 11 text

利用例2 : スーパークラスのコンストラクタ引数の準備 <適用前> public class Sub extends Super { private static String format(int zipCode) { return zipCode.substring(0, 3) + "-" + zipCodee.substring(3); } public Sub(int zipCode) { super(format(zipCode));   } } <適用後> public class Sub extends Super { public Sub(int zipCode) { String code = zipCode.substring(0, 3) + "-" + zipCodee.substring(3); super(code);   } } 11

Slide 12

Slide 12 text

利用例 3 : スーパークラスのコンストラクタ引数の共有 <適用前> public class Super { public Super(C x, C y) { ... } } public class Sub extends Super { private Sub(C x) { super(x, x); } public Sub(int i) { this(new C(i)); } // 親クラスの初期化に必要な準備 } <適用後> public class Sub extends Super { public Sub(int i) { var x = new C(i); super(x, x); } } 12

Slide 13

Slide 13 text

利用例 4 : フィールドへの早期割り当て <適用前> class Super { // override側が呼ばれるが、初期化されていないので、0になる。 Super() { overriddenMethod(); } void overriddenMethod() { System.out.println("hello"); } } class Sub extends Super { final int x; Sub(int x) { /* super(); */ // 暗黙的呼び出し this.x = x; } @Override void overriddenMethod() { System.out.println(x); } } 13

Slide 14

Slide 14 text

<適用後> class Super { // 初期化を先に実行しているのでSub(1)の場合、1が印字される。 Super() { overriddenMethod(); } void overriddenMethod() { System.out.println("hello"); } } class Sub extends Super { final int x; Sub(int x) { this.x = x; super(); } @Override void overriddenMethod() { System.out.println(x); } } 14

Slide 15

Slide 15 text

447を 477って書いてる・・・ orz 15

Slide 16

Slide 16 text

正直、 JEP482(利用例4)の書き方で嬉しくなる具体例あるか?と 思ってしまいました。 。 。 こういう時こそ、 Java User Groupの方々に助けてもらおう! 思いついた方いらっしゃったら、教えてください・・・! 16

Slide 17

Slide 17 text

制約 17

Slide 18

Slide 18 text

未初期化のフィールドアクセスの禁止 class A { int i; A() { System.out.print(this); // Error var x = this.i; // Error this.hashCode(); // Error var x = i; // Error hashCode(); // Error super(); } void m(); } class B extends A { B() { var x = super.i; // Error super.m(); // Error super(); } } 18

Slide 19

Slide 19 text

ご清聴ありがとうございました! 19