Javaにデータクラスやパターンマッチングが導入される?

DevoxxでのBrian Goetzのプレゼンで、Javaにデータクラスやパターンマッチを入れるというアイデアが発表されていました。

Oracleの資料では、必ず最初に「将来の仕様について約束したりするものではないですよ」というスライドが入りますが、今回のプレゼンではそこをかなり強調していますね。


Java9に入ることはないけど、Java10でも入るかどうか、そもそも検討されるかどうかもわかんないみたいな話です。
けど、このような仕様が技術的には実装可能ということではあると思うので、興味深いです。
また、パターンマッチするときに、varによって型推論されることが前提となっているというのも面白いところ。

Data Class

よくJavaでは

class Point {
  final int x;
  final int y;
}

のようなデータホルダーのようなクラスをたくさん定義しますね。んで、そこにはsetter/getterやコンストラクタ、equalsメソッドやらtoStringメソッドやらが必要になります。
これをIDEで自動生成したりLombok使ったりということはできるけど、こんな感じで書けるようにしてはどうかと。

class Point(int x, int y) {}


IDEでの生成やLombokと違うのは、コンパイラに「これはデータ格納クラスですよ」っていうのを伝えれること。
ただし、コンストラクタでバリデーションしたいときはどうするかとか、equalsをカスタマイズしたかったらどうするかとか、これってマクロじゃね?とか、いろいろあるよ、ということらしい。

switchの拡張

switchは便利だけど、整数やStringやenumしか使えないし、caseの条件も定数だけなので、ちょっと困るから拡張しようという話。
型によって処理をわけるときにこんなコードを書きます。

Object comp = getComponent();
String message;
if (comp instanceof Integer) {
  int i = (Integer)comp;
  message = "整数やね " + i;
} else if (comp instanceof String) {
  String s = (String)comp;
  message = s.length() + "文字の文字列やね";
} else {
  message = "ようしらん";
}
print(message);

ここで、else ifってswitchより見づらいよねっていう話と、instanceofしてるのにキャストする必要ある?って話があります。
kotlinではinstanceofしたifブロックではキャスト不要になったりしますね。


んで、こんな感じに書けるようにしてはどうかと。

Object comp = getComponent();
String message;
switch (comp) {
 case Integer i:
   message = "整数やね " + i;
   break;
 case String s:
   message = s.length() + "文字の文字列やね";
   break;
 default:
   message = "ようしらん";
}
print(message);

switch式

さらにこれ、式にしたらよくね?という話

Object comp = getComponent();
String message =
  switch (comp) {
    case Integer i -> "整数やね " + i;
    case String s -> s.length() + "文字の文字列やね";
    default -> "ようしらん";
  }
print(message);

なんか素敵。

Data ClassとSwitch

そしてさらに、caseにData Classのコンストラクタを指定できると便利よね、という話。

Object comp = getComponent();
String message =
  switch (comp) {
    case Point(var x, var y) -> String.format("点(%d,%d)やね", x, y);
    case Integer i -> "整数やね " + i;
    case String s -> s.length() + "文字の文字列やね";
    default -> "ようしらん";
  }
print(message);

こうなると、instanceof、cast、フィールドの値とりだし、変数への割り当てができて便利。
さらに

  case Point(0, 0) -> ...

とか書いたり

  case Line(Point(0, y), _) -> ...

とか、入れ子にしたりワイルドカード使えるとさらに便利。
ま、他の言語にはすでにあるんだけど。


という初夢をみました。