Lombok ライブラリ - その他
主記事
Lombok ライブラリ - Status Code 303 - See Other
この記事では、クラスとフィールド以外に関連するアノテーションを記述。
(記事執筆時のバージョン :v1.16.6)
(更新中)
データ同期
型推論
val
ローカル変数にのみ使用可能であり、初期化の式から型を推測する。
また、val を定義したローカル変数は、final になる。
例:
val x = 10.0; val y = new ArrayList<String>();
と記述すれば、 val は以下と同等とみなされる。
final double x = 10.0; final ArrayList<String> y = new ArrayList<String>();
なお、あまりそうは見えないかもしれないが val はアノテーション型である。(正確にはシンタックスシュガーらしい)
なぜなら、 val x = 10.0; と記述すれば、Lombok は @val final int x = 10; にコードを変換するから。
詳細はこちら(val)
オプション
なし。
ツールに対する適用外設定
@Generated
いずれは、Lombok が生成したメソッドやクラスに自動的に付加するアノテーション。
全てのコードスタイルチェックツールやバグ発見ツールに対して、これらのコードを無視させるために使用する。
オプション
なし。
メソッドパラメータの null チェック自動生成
リソース解放処理の自動生成
@Cleanup
何が起こったかに関係なく、ローカル変数がそれらの close メソッド呼び出しによってリソースの解放を保証する宣言。
ローカル変数の有効範囲にある全ての命令文を包括した try 文を実装することにより、リソースを解放する。
詳細なドキュメントこちら(@Cleanup)。
例:
public void copyFile(String in, String out) throws IOException { @Cleanup FileInputStream inStream = new FileInputStream(in); @Cleanup FileOutputStream outStream = new FileOutputStream(out); byte[] b = new byte[65536]; while (true) { int r = inStream.read(b); if (r == -1) break; outStream.write(b, 0, r); } }
これらの宣言が Lombok によって以下の処理に変換される。
public void copyFile(String in, String out) throws IOException { @Cleanup FileInputStream inStream = new FileInputStream(in); try { @Cleanup FileOutputStream outStream = new FileOutputStream(out); try { byte[] b = new byte[65536]; while (true) { int r = inStream.read(b); if (r == -1) break; outStream.write(b, 0, r); } } finally { if (out != null) out.close(); } } finally { if (in != null) in.close(); } }
チェック例外 → 実行時例外変換
@SneakyThrow
Java では、メソッド処理内にチェック例外を生成し得る命令が記述された場合、その例外に対処しなければならない。
(try-catch 文で例外をキャッチするか、メソッド呼び出し元に伝播させるなら throws 宣言を使ったりする)
しかし、このアノテーションをメソッドに記述すると、本来行うはずのチェック例外に対処しなくても良くなる。
このアノテーションは、内部的にオプション(value)に指定されたチェック例外(複数可)を
RuntimeException もしくは他の実行時例外にラップしている。こうして、チェック例外が実行時例外内に隠れるため、
本来 JVM が行うはずだった、チェック例外における一貫性チェックを回避している。
例:
下記のバイト列を特定の文字コードから String インスタンスを生成するコンストラクタはチェック例外である
UnsupportedEncodingException をスローするため、本来は何かしら対処をしなければならない。
しかし、以下の例では、これを省略してもプログラムは正常に動作する。
@SneakyThrows(UnsupportedEncodingException.class) public void utf8ToString(byte[] bytes) { return new String(bytes, "UTF-8"); }
これは、Lombok が上記コードを内部的に下記のように変換しているから。
public void utf8ToString(byte[] bytes) { try { return new String(bytes, "UTF-8"); } catch (UnsupportedEncodingException $uniqueName) { throw useMagicTrickeryToHideThisFromTheCompiler($uniqueName); // This trickery involves a bytecode transformer run automatically during the final stages of compilation; // there is no runtime dependency on lombok. } }
なお、元のコードと同じ動きを保証するために発生する条件では、本来スローされるべき例外がスローされる。
import java.text.SimpleDateFormat; import lombok.SneakyThrows; public class Main { @SneakyThrows public static void main(String[] args) { System.out.println(new SimpleDateFormat("yyyyMMdd").parse("aaaaa")); // 意図的に例外(ParseException)を発生させる } }
出力結果。
Exception in thread "main" java.text.ParseException: Unparseable date: "aaaaa" at java.text.DateFormat.parse(DateFormat.java:366) at Main.main(Main.java:8)
詳細はこちら(@SneakyThrows)