Java で静的メタプログラミングは可能ですか?
-
02-07-2019 - |
質問
私はのファンです C++ の静的メタプログラミング. 。Java にジェネリックがあることは知っています。これは、静的メタプログラミング (つまり、コンパイル時のプログラム実行) が Java で可能であることを意味しますか?もしそうなら、それについて詳しく学べる良いリソースを誰かが推薦してもらえますか?
解決
いいえ、それは不可能です。ジェネリックはテンプレートほど強力ではありません。たとえば、テンプレート引数はユーザー定義型、プリミティブ型、または値にすることができます。ただし、一般的なテンプレート引数は次のようにすることしかできません。 Object
またはそのサブタイプ。
編集:これは古い答えです。2011 年以降、Java 7 が導入されました。 このようなトリックに使用できるアノテーション.
他のヒント
を見てみましょう クロージュア. 。これは、JVM 上で実行され、Java との相互運用性が高いマクロ (メタプログラミング) を備えた LISP です。
「静的メタプログラミング」とは正確には何を意味しますか?はい、C++ テンプレートのメタプログラミングは Java では不可能ですが、C++ のメソッドよりもはるかに強力な他のメソッドが提供されます。
- 反射
- アスペクト指向プログラミング (@AspectJ)
- バイトコード操作 (Javassist、ObjectWeb ASM、Java エージェント)
- コード生成 (アノテーション処理ツール、Velocity などのテンプレート エンジン)
- 抽象構文ツリーの操作 (一般的な IDE によって提供される API)
- Java コンパイラを実行し、実行時でもコンパイルされたコードを使用する可能性
最善の方法はありません。これらの方法にはそれぞれ長所と短所があります。JVM の柔軟性により、Java のこれらのメソッドはすべてコンパイル時と実行時の両方で使用できます。
いいえ。さらに、ジェネリック型はコンパイラによって上限まで消去されるため、実行時にジェネリック型 T の新しいインスタンスを作成することはできません。
Java でメタプログラミングを行う最善の方法は、型の消去を回避して、 Class<T>
タイプ T のオブジェクト。ただし、これは単なるハックです。
いいえ、Java のジェネリックスは純粋に Object のキャストを回避する方法です。
Java の強力なコンパイル時ロジックが必要な場合、それを行う 1 つの方法は、ある種のコード生成を使用することです。他の投稿者が指摘しているように、Java 言語にはコンパイル時ロジックを実行するのに適した機能が備わっていないため、これが最良の選択肢になる可能性があります (本当にコンパイル時ロジックが必要な場合)。他の可能性をすべて使い果たしたら、 もちろん コード生成をしたい場合は、私のオープン ソース プロジェクト Rjava に興味があるかもしれません。次の場所から入手できます。
http://www.github.com/blak3mill3r
これは、Ruby で書かれた Java コード生成ライブラリであり、Ruby on Rails アプリケーション用の Google Web Toolkit インターフェイスを自動的に生成するために作成しました。そのためには非常に便利であることがわかりました。
警告として、Rjava コードをデバッグするのは非常に難しい場合があります。Rjava はあまりチェックを行わず、ユーザーが何をしようとしているのかを理解していると想定しているだけです。とにかく、これが静的メタプログラミングのほぼ現状です。C++ TMP を使用して行う些細な作業よりもデバッグが大幅に簡単で、同様の用途に使用することが可能です。
とにかく、Java ソース コードを出力するプログラムの作成を検討している場合は、今すぐやめて Rjava をチェックしてください。まだ望み通りの機能を備えていないかもしれませんが、MIT ライセンスを取得しているので、自由に改良したり、揚げたり、おばあちゃんに販売したりできます。一般的なプログラミングの経験がある他の開発者に設計についてコメントしてもらえると嬉しいです。
ロンボク島 コンパイル時メタプログラミングの弱い形式を提供します。しかし、彼らが使うテクニックは、 完全に一般的な.
見る コンパイル時に Java コードを変換する 関連するディスカッションのために
静的メタプログラミングの利点を理解しているかどうかはわかりません。
Java では、クラスに関する情報を探したり、メタプログラミングで行うすべてのことを反映したりすることができます。新しい構文やさまざまな考え方を追加することなく、コード内でそれらを実行するだけです。アノテーションは、より構造化された方法で特定のメタプログラミング タスクを実行することもできます。
これについては私が間違っている可能性があります。理解できるかどうかわからないため、真剣に質問することを検討しています。静的メタプログラミングは、一部の言語では実行時に利用できるコンパイル時情報があまり保持されていないという事実 (Java と動的言語の長所の 1 つ) を回避する巧妙なハックのようです。
メタプログラミングがリフレクションよりも理解しやすく読みやすい、またはその他の点で優れたソリューションを提供する例へのリンクを返信していただければ、その努力に感謝します。
の マニホールドプロジェクト タイプセーフを提供します 静的 Java のメタプログラミング。これを使用すると、Javac が型名を解決するため、コンパイル時に動的に型を構築できます。の JSON スキーマのデモ は、動的なコンパイル時の型投影に関する静的メタプログラミングを示します (コード生成ビルド ステップはありません)。
さらに、Manifold を使用して新しい機能を追加することもできます。チェックアウト 構造型付け, メソッド拡張, 、 そして タイプセーフなリフレクション. .