ロンボクプロジェクト、または定型的な戦争の宣言

アメリカではなく、Pandoraのボックスを開きます。Javaコードには多くの定型文があります。 典型的なゲッター、セッターとコンストラクター、遅延初期化のメソッド、メソッドtoString、hashCode、equals、スローされない例外ハンドラー、スレッドクローザー、同期ブロック。 問題は、これらすべてを書くことすらありません。現代の開発環境は、いくつかのキーを押すことでそのようなタスクに対処します。 コードに変更が加えられると、定型文を最新の状態に保つことが困難になります。 また、場合によっては(マルチスレッド、hashCodeおよびequalsメソッドの実装)、エラーなしでテンプレートコード自体を作成するのは簡単な作業ではありません。 この問題の解決策の1つはコード生成です。この記事では、Lombokプロジェクトについて説明ます。 。



ロンボク島を接続



Lombokは、Java 6の注釈処理エンジンを使用します。Java6からは、最低限の環境要件に従います。 Lombokをプロジェクトに接続するには、依存関係をオンにします。 Mavenを使用する場合、これは次のように行われます。



<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>0.11.0</version> <scope>provided</scope> </dependency>
      
      





Lombokのほとんどの機能では、このライブラリはコンパイル段階でのみ必要です。 現時点のLombokの最新バージョン(0.11.0)はまだMavenの中央リポジトリに到達していませんが、サイトからダウンロードすることでローカルまたは企業のリポジトリに問題なくインストールできます。



アクセサにさよならを言う



Javaの定型文の主なソースの1つは、言語レベルでのプロパティの欠如です。 OOPの原則に従って、フィールド宣言ごとに少なくとも6つの標準行(getterおよびsetter)を記述する必要があります。 SpringやTapestryなどの一部のライブラリは、場合によっては、その目的のために、開発者がバイトコード自体にアクセサを挿入することでアクセサを忘れることができます。 同様の機能がLombokによって提供されています。



  public class GetterSetterExample { @Getter @Setter private int age = 10; @Setter(AccessLevel.PROTECTED) private String name; @Getter(lazy=true) private final Map<String, String> map = initMap(); }
      
      





ゲッターアノテーションパラメーターlazy = trueを使用すると、レイジーフィールドの初期化を実装できます。この場合のinitMap()メソッドの呼び出しは、最初のゲッター呼び出しまで遅延され、 ダブルチェックロックとしてスレッドセーフ初期化にラップされます。



デザイナーの破壊



POJOクラスのコンストラクターも複雑さや多様性に違いはありません-ほとんどの場合、このリストから何かが必要です:パラメーターなしのコンストラクター、すべてのパラメーターを持つコンストラクター、いくつかの必須パラメーターのみを持つコンストラクター、静的ファクトリーメソッド。 Lombokは、アノテーション@ NoArgsConstructor、@ AllArgsConstructor、@ RequiredArgsConstructor、およびstaticNameパラメーターをそれぞれ使用して、簡単にこれを実行します。



 @RequiredArgsConstructor(staticName = "of") @AllArgsConstructor(access = AccessLevel.PROTECTED) public class ConstructorExample<T> { private String name; @NonNull private T description; }
      
      





結果として得られるものは次のとおりです。



 public class ConstructorExample<T> { private String name; @NonNull private T description; private ConstructorExample(T description) { if (description == null) throw new NullPointerException("description"); this.description = description; } public static <T> ConstructorExample<T> of(T description) { return new ConstructorExample<T>(description); } @java.beans.ConstructorProperties({"name", "description"}) protected ConstructorExample(String name, T description) { if (description == null) throw new NullPointerException("description"); this.name = name; this.description = description; }
      
      







標準メソッドを生成します:toString、hashCode、equals



equalsメソッドとhashCodeメソッドの正しい実装についてはかなり多くのことが書かれています。このテーマに関するBlok のEffective JavaOderskyの記事を思い出してください 。 要するに、それらを正しく実装することは容易ではなく、それらを最新の状態に保つことはさらに難しく、クラスのかなりの半分を占めることができると言えます。 toStringメソッドは、コードの正確性にとってそれほど重要ではありませんが、クラスを変更するたびに更新することはあまり快適ではありません。 Lombokには、次の2つの簡単な注釈を使用して、この感謝のない仕事をする機会を与えます。



 @ToString(exclude="id") @EqualsAndHashCode(exclude="id") public class Person { private Long id; private String name; ... }
      
      







目に見えないロガー



人気のあるロギングライブラリのいずれかを使用する場合、ほとんどの場合、各クラスで静的ロガー宣言があります。



 public class Controller { private static final Logger log = LoggerFactory.getLogger(Controller.class); public void someMethod() { log.debug("someMethod started");
      
      





代わりに、Lombokは、好みのロギングファシリティに応じて、アノテーションLog 、@CommonsLog、@ Log4j、または@ Slf4jを使用することをお勧めします。



 @Slf4j public class Controller { public void someMethod() { log.debug("someMethod started");
      
      







ローカル変数を完成させる



最終的なローカル変数の使用は優れたプログラミングスタイルですが、静的型付けとJavaの型推論がないため、特に洗練されたマップが画面からはみ出してしまう可能性があります。 JavaからScalaまたはGroovyにまだ切り替えたくない場合は、次のLombokハックを使用できます。



 public class ValExample { public String example() { val map = new HashMap<String, Map<String, String>>(); for (val entry: map.entrySet()) { ...
      
      





この場合のマップ変数はfinalとして宣言されますが、そのタイプの説明は割り当て式の右側から取得されます。



免責で例外を投げる



残念ながら、すべての開発者が、ここで既に言及した「Effective Java」ブロックまたはStusting Robust Javaを読むわけではありません。 または多分彼らは読むが、あまり注意深くない。 または、おそらく、彼らは本当にこの特定の例外をチェックすることを宣言する何らかの根拠のある動機を持っていました-しかし、これはあなたにとって簡単ではありません。 たとえば、システムがUTF-8エンコーディングをサポートしていない場合、アプリケーションが機能しないことが確実な場合、UnsupportedEncodingExceptionで何をする必要がありますか? try-catchでコードをラップし、待機することのないログに無意味な出力を書き込む必要があります。例外を生成される予定のないランタイムラッパーに変換するか、空のインターセプトブロックで無視します(方法はわかりません)あなた、そして私は常にリボルバーを手にしたいという欲求を喚起します。 ロンボク島もここで代替手段を提供します。



  public class SneakyThrowsExample implements Runnable { @SneakyThrows // "  !" public void run() { throw new Throwable(); // "   !" } }
      
      





この魔術では、他のすべてとは異なり、実行時にLombokに接続する必要があります。 簡単です。Lombokは、tryで例外をキャッチしてコンパイラーの警戒を緩和し、実行時に例外をキャッチしてcatchに再スローします。 秘Theは、バイトコードレベルで、メソッドシグネチャで宣言されていない例外を含め、あらゆる例外をスローできることです。



正しい同期



マルチスレッドはプログラミングの非常に複雑な領域であり、Javaには独自のイディオムとパターンがあります。 パブリックロックでは、接続されていない機能の一部を同期する必要がある場合があり、不要なロックやキャッチしにくいエラーが発生する可能性があるため、同期のプライベートフィールドを使用することをお勧めします。 Lombokは、静的メソッドとインスタンスメソッドの両方で、@ Synchronizedアノテーションでマークされたメソッドのコンテンツを正しく同期できます。



 @Synchronized public static void hello() { System.out.println("World"); } @Synchronized public int answerToLife() { return 42; }
      
      





取得するものは次のとおりです。



 private static final Object $LOCK = new Object[0]; private final Object $lock = new Object[0]; public static void hello() { synchronized($LOCK) { System.out.println("world"); } } public int answerToLife() { synchronized($lock) { return 42; } }
      
      







IDEは何と言っていますか?



EclipseやIntelliJ IDEAでプロジェクトを開くときに、コードの行がコンパスの正しい怒りから赤く燃え上がっていたら、これらのすばらしい機能はすべて価値がなかっただろう。 幸いなことに、開発環境との統合が利用可能であり、非常に優れています。 IntelliJ IDEAの場合、プラグインは標準リポジトリにあります。







EclipseとNetBeansの場合、インストールは少し珍しいです。 lombok.jarファイルを実行する必要があります。このファイルには、Lombokを既存のEclipseインストールにロールするための優れたインストーラーが表示されます。







これらのプラグインは、開発環境に、ゲッター、セッター、およびボイラープレートのその他の要素がないとさえ思わないことを確信させるだけでなく、たとえば、生成されるゲッターがすでにクラスに存在する場合のエラー状況も正しく強調表示します:







Lombokの主な機能をリストしましたが、それだけではありません。 より詳細には、すべての属性を持ち、「前」と「後」のコードを比較したすべての可能な注釈がドキュメントに記載されています




All Articles