AST変換-重質物質への最初のステップ

そして、Javaコードで魔法をかけましょう。 以下がその1つです。





これを取る:

import groovy.transform.Canonical import groovy.transform.TupleConstructor @Canonical @TupleConstructor class Person { int id String firstName String lastName Date birthdate }
      
      





コンパイルすると、バイトコードでこれに類似したものが得られます。

100行を超えるHellのJavaボイラープレート
 import java.util.Date; import java.util.Map; public class Person { private int id; private String firstName; private String lastName; private Date birthdate; //   @TupleConstructor- public Person(Map parameters){ this.id = (int) parameters.get("id"); this.firstName = (String) parameters.get("firstName"); this.lastName = (String) parameters.get("lastName"); this.birthdate = (Date) parameters.get("birthdate"); } public Person(int id, String firstName, String lastName, Date birthdate) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.birthdate =birthdate; } public Person(int id, String firstName, String lastName) { this(id, firstName, lastName, null); } public Person(int id, String firstName) { this(id, firstName, null, null); } public Person(int id) { this(id, null, null, null); } public Person() { this(0, null, null, null); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; if (id != person.id) return false; if (birthdate != null ? !birthdate.equals(person.birthdate) : person.birthdate != null) return false; if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null) return false; if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null) return false; return true; } @Override public int hashCode() { int result = id; result = 31 * result + (firstName != null ? firstName.hashCode() : 0); result = 31 * result + (lastName != null ? lastName.hashCode() : 0); result = 31 * result + (birthdate != null ? birthdate.hashCode() : 0); return result; } @Override public String toString() { return "Person{" + "id=" + id + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", birthdate=" + birthdate + '}'; } public int getId() { return this.id; } public void setId(int paramInt) { this.id = paramInt; } public String getFirstName() { return this.firstName; } public void setFirstName(String paramString) { this.firstName = paramString; } public String getLastName() { return this.lastName; } public void setLastName(String paramString) { this.lastName = paramString; } public Date getBirthdate() { return this.birthdate; } public void setBirthdate(Date paramDate) { this.birthdate = paramDate; } }
      
      









まあ、はい、いいです。 しかし、このボイラープレート全体を生成して非表示にする優れたIDEの能力は言うまでもなく、 Lombokにはユニークなものはありません。



なぜGroovyなのか、なぜAST変換なのか?

この記事では、JavaプロジェクトでGroovy AST変換を使用する理由を簡単に実証し、(再び)今日のGroovyでのAST変換を説明します。 理由がすでにわかっていて、「方法と内容」だけが必要な場合は、「AST変換の概要」まで大胆にスクロールしてください。



それでは、なぜロンボクではなくAST変換なのでしょうか?



まず、AST変換を使用するために、Groovyを知ったり、Groovyを作成したり、実行時にGroovyを実行したりする必要はありません。 変換はソートのコンパイル中に発生し、Groovyは1つのjarによって依存関係のリストに追加されます。 それだけです

したがって、AST変換は、Groovyをプロジェクトに「ドラッグ」するための優れた方法です。「ほら、ボス、大丈夫、これはボイラーボイラーを処理するための単なるライブラリです!」 そしてもちろん、Gradleでのビルドの背後にあるSpockでのテストにより、実際のGroovyがコードに表示されます(動的、機能的、エレガント)。 AST変換は最初のステップにすぎません。

さらに、AST変換はLombokよりもはるかに拡張性が高く、強力で多用途です。

最後になりましたが、AST変換は、Eclipseだけでなく、Groovy対応のIDEでも完全にサポートされています。

LombokとAST変換のフロントエンドの比較は明らかにこの記事の範囲を超えているので、そこで停止しましょう。



バイトコードの生成はソースコードの生成よりも大きな利点があることは当然のように思えます(そして、腹を立てないようにエディターで「崩壊」します)-生成はコンパイル中に行われ、「サポート」する必要はありません。 1つの例は、IntelliJ IDEAがハッシュコードと同等を完全に生成することです。 新しいフィールドを追加するとき、ペンを使用してこれら2つのメソッドを消去し、再度生成します。 ふう。



Java開発者とGroovy開発者の両方にとってのAST変換の利点については、他にも多くのことが述べられていますが、その考えが明確であることを願っています。 練習に移りましょう。



AST変換の概要



もちろん、Groovyで最も重要な利点の1つは、 メタプログラミングです。 コンパイル時と実行時の2つのタイプがあります。

ランタイムメタプログラミングはおおよそ「ああ、存在しないメソッドを呼び出しましたか?」 怖くはありません。このメソッドを呼び出したときに考えていたことに基づいてスレッドを作成します。」 これには多くの例があります-ほぼすべてのGroovyライブラリーは、ビルダー、スラーパー、Grails、Ratpack、Gradleなど、すべてのものに基づいています。 しかし、今はそれについてではありません(これについて知りたい場合は、投稿の最後にある厚かましいPRの段落1を参照してください)。



次に、コンパイル中のメタプログラミングについて説明します。つまり、単純にコードにメタプログラミングを記述し、バイトコードに別のメタコードを取得する方法(まあ、または余分なもの)について説明します。



変換から始めましょう。これは、Groovy自体にフラッシュされており、注釈やその他の付加物はありません。

私たちは書きます:

 class Person { String name }
      
      





出力は、すべてのフィールドがprivate



(この場合はname



)であるバイトコードであり、すべてのゲッターとセッターが書き込まれます(まあ、この場合はgetName()



setName(String name)



ですが、アイデアは明確です)。



この美しい小さなことは、コンパイル時のメタプログラミングの完全な例です。



ボイラープレートからのこの小さな配達を見て、素晴らしい男のダンノ・フェリンはこう言いました。「しかし、ゲッターとセッターを除いて、まだ多くのボイラープレートがあり、それらはすべて同じではありません! それでAST変換が生まれました(最初の、奇妙なことに、 @Bindable



。ただし、どのくらいのコードがスローされるかを見てみると、奇妙で​​はないかもしれません)。



AST変換は、Groovyのコンパイル中にオンザフライで抽象構文ツリーを変更する注釈のコレクションです。 ゲッターとセッターの追加は、アノテーションを追加しなくても常に機能する組み込みのAST変換であると言えます。 残りはオンデマンドでのみ含まれます。



私たちが持っているものを見てみましょう:



そして、それだけではありません! アーチの重要な@CompileStatic



@Field



、および@Field



性に苦しむことに耐える一連の注釈もありますが、それでも別の時間です(まあ、または投稿の最後に厚かましいPRのポイント1を参照してください)。



PSこれが何であるかを知ったので、新しいAST変換をどのように 、そしてどのように書くかについての 2つの興味深い記事があります 。 下のPRのパラグラフ2の同じものを参照してください。



そして今、2点からの無作法なPR:

  1. Grooveをゼロから高度なポイントまで必要としている人は、モスクワで4 月17日、カザンで4月15 日にトレーニングに行きます(ノックalexbel
  2. 抽象構文ツリーが解体され、定型文でゴキブリと戦うために独自のAST変換を記述している人は、4月18日のJPointと4月16日のJavaDay Kazanに関するレポート行きます(再びalexbelをノックします



All Articles