Tech Hotoke Blog

IT観音とは私のことです。

【Java】Java17 まとめ~Java8との変更点~

f:id:TechHotoke:20211216134400p:plain

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が含まれている。


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のような実装クラスとともに 用いる必要がある。

参考