Java17についてまとめ~Java8からの変更点part1~
Java17
- 2021年9月リリース
- Java11以来のLTS版という事で注目度高い
- Java10以降半年一回のリリース、3年ごとのLTSが発表されるというサイクルに固定化された
- LTS版は3年LTS版でないJavaはサポート期間が半年( Oracle)
Java8の方がJava11よりも最大4年サポート期間が長い。
Java8→Java17への乗り換えの方がリスクが低いのでは...?
2018年にリリースされた最初のLTS(long-term support)であるJDK 11以降の14のJEPが含まれている。
- 306: 厳密性を維持する浮動小数点セマンティクスの復活
- 356: 仮想乱数生成器の強化
- 382: 新しいmacOSレンダリングパイプライン
- 391: macOS/AArch64への移植
- 398: Applet APIの削除に向けた非推奨化
- 403: JDK内部のカプセル化の強化
- 406: switchパターンマッチング(プレビュー)
- 407: RMIアクティベーションの削除
- 409: Sealedクラス
- 410: 実験的AOTおよびJITコンパイラの削除
- 411: Security Managerの削除に向けた非推奨化
- 412: 他言語関数とメモリAPI(インキュベータ)
- 414: Vector API(セカンドインキュベータ)
- 415: コンテキスト固有のデシリアライズフィルタ
Java8からの変更点
Recordクラス
Recordクラスとは?
- ファイルやソケットで入出力するデータを扱うためのクラスや、データベースに出し入れするためのデータを扱うクラスのようなデータの入れ物としてのクラス
- 従来の冗長な記述(setter/getter など)を排除することが可能
- immutableな性質を持つ
Recordの書き方
定義
record Bike( String model, int disp, boolean big){
}
呼び出し
var cbr = new Bike(" 600 F 4 i", 599, true);
System.println(cbr.model())
レコード定義時のパラメータ名がそのままgetterとなる。
String model, int disp, boolean big){
public Bike( String model, int disp, boolean big){
if( disp > 400 && !big){
throw new IllegalArgumentException( model + " should be big");
} else if( disp <= 400 && big){
throw new IllegalArgumentException( model + " shouldn' t be big");
}
this. model = model;
this. disp = disp;
this. big = big;
}
}
public float dispAsLiter(){
return disp / 1000. 0 f;
}
}
上記のようにコンストラクタを作成し、その中でバリデーションを行うことも可能
メソッドを別途定義することも可能。
基本的な使い方はclassと変わらない。
注意
immutableな性質を持つ=setterは存在しない
あとからフィールド値を上書きすることはできない。
たとえば データベースから検索してきたデータを加工して設定し、それをファイル へ 出力する ようなことはできない。
実態
実態としてはjava.lang.Recordクラスを継承したclassとしてコンパイルされる。
また、各フィールドはfinalとして定義されている。(immutableの正体)
getterや共通コードなどはコンストラクタが定義されている。
Compiled from "Bike. java"
final class Bike extends java. lang. Record {
Bike( java. lang. String, int, boolean);
public final java.lang. String toString();
public final int hashCode();
public final boolean equals( java. lang. Object);
public java. lang. String model();
public int disp();
public boolean big();
}
Sealed
Java の クラス や インタフェース( 以降、 まとめ て「 タイプ)は 誰でも継承できるか、final 宣言することで誰も 継承でき ないかの 0 か100 かの二択だった。
これに対して、明示的に指定 さ れ たタイプにだけ 継承 を 許可 することが可能になる仕組み。
スーパータイプの作者が明示的に継承先を指定できるようになったため、システム的にAPIの整合性を守れるようになったことが大きなメリットとして挙げられる。
使い方
public sealed interface Motor permits RocketMotor, MotorBike, Car {}
クラス・インターフェイス宣言の直前にsealed宣言する
タイプの直後にpermits句を宣言(permitsされるクラスが同一のソースだけにあるのであれば、permitsは省略できる)
permits句にカンマ区切りで継承を許可するtypeを明示する
継承制限の継承
permits 句 で指定したサブタイプの継承制限は継承されない。
この ため、明示 的にSealedである かどうかを 示す必要 がある。
- サブ タイプ も Sealed に し て 継承 先 を 制限 し たい 場合 は sealed 宣言
- Sealed に し たく ない 場合 は non-sealed 宣言
- それ 以上 継承 をさ せ たく ない 場合 は final 宣言
を行う。
制約
permits句で指定したtypeは同一モジュール内にある必要がある。
より詳しく
https://www.infoq.com/jp/articles/java-sealed-classes/
HTTP/2のサポート
-
同期/非同期
HttpClientでは同期的な通信だけでなく、非同期通信もサポートします。
レスポンスはCompletableFutureで受け取れるため、レスポンス受信後の処理を非同期前提に記述できる。
-
ReactiveStream
HttpClientをFlowAPIを用いたReactive Streamで扱うことができ る。
ただし利用にはFlowの実装、あるいはAkka Streamsのような実装クラスとともに 用いる必要がある。
参考
-
WEB + DB PRESS
-
Oracle公式
-
JEP
Discussion