誰かがJavaの内部で注釈がどのように機能するかを私に説明できますか?
Javaでjava.lang.annotationライブラリを使用してカスタムアノテーションを作成する方法を知っています。しかし、たとえば、@ Overrideアノテーションなど、内部でどのように機能するかはまだわかりません。
どなたか詳しくご説明いただければ幸いです。
誰かがJavaの内部で注釈がどのように機能するかを私に説明できますか?
Javaでjava.lang.annotationライブラリを使用してカスタムアノテーションを作成する方法を知っています。しかし、たとえば、@ Overrideアノテーションなど、内部でどのように機能するかはまだわかりません。
どなたか詳しくご説明いただければ幸いです。
回答:
アノテーションの種類の最初の主な違いは、それらがコンパイル時に使用されてから破棄される(のように@Override
)か、コンパイル済みクラスファイルに配置されて実行時に使用できる(Springのように@Component
)かです。これは、アノテーションの@Retentionポリシーによって決定されます。独自のアノテーションを作成する場合、そのアノテーションが実行時に役立つか(おそらく自動構成の場合)、コンパイル時にのみ役立つか(チェックまたはコード生成の場合)を決定する必要があります。
注釈付きのコードをコンパイルする場合、コンパイラーは、アクセス修飾子(public
/ private
)やのようなソース要素の他の修飾子と同じように注釈を表示しますfinal
。アノテーションに遭遇すると、特定のアノテーションに興味があると言うプラグインクラスのようなアノテーションプロセッサを実行します。注釈プロセッサは通常、リフレクションAPIを使用してコンパイルされる要素を検査し、それらの要素に対してチェックを実行したり、要素を変更したり、コンパイルする新しいコードを生成したりできます。@Override
最初の例です。リフレクションAPIを使用して、スーパークラスの1つでメソッドシグネチャの一致を検出できることを確認し、一致しMessager
ない場合はを使用してコンパイルエラーを発生させます。
注釈プロセッサの作成に関するチュートリアルは多数あります。ここに便利なものがあります。インターフェースのメソッドを調べて、コンパイラーが注釈プロセッサーを呼び出す方法を確認しProcessor
ます。主な操作はprocess
メソッドで行われます。このメソッドは、一致する注釈を持つ要素をコンパイラが検出するたびに呼び出されます。
他の人が提案したことに加えて、カスタマイズされた注釈とそのプロセッサをゼロから記述して、注釈の動作を確認することをお勧めします。
たとえば、私自身では、コンパイル時にメソッドがオーバーロードされているかどうかを確認するための注釈を記述しました。
まず、という名前の注釈を作成しますOverload
。この注釈はメソッドに適用されるので、注釈を付けます@Target(value=ElementType.METHOD)
package gearon.customAnnotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(value=ElementType.METHOD)
public @interface Overload {
}
次に、定義された注釈によって注釈が付けられた要素を処理するための対応するプロセッサを作成します。によって注釈が付けられたメソッドの場合@Overload
、そのシグニチャーは複数回出現する必要があります。または、エラーが出力されます。
package gearon.customAnnotation;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
@SupportedAnnotationTypes("gearon.customAnnotation.Overload")
public class OverloadProcessor extends AbstractProcessor{
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// TODO Auto-generated method stub
HashMap<String, Integer> map = new HashMap<String, Integer>();
for(Element element : roundEnv.getElementsAnnotatedWith(Overload.class)){
String signature = element.getSimpleName().toString();
int count = map.containsKey(signature) ? map.get(signature) : 0;
map.put(signature, ++count);
}
for(Entry<String, Integer> entry: map.entrySet()){
if(entry.getValue() == 1){
processingEnv.getMessager().printMessage(Kind.ERROR, "The method which signature is " + entry.getKey() + " has not been overloaded");
}
}
return true;
}
}
アノテーションとそのプロセスをjarファイルにパッケージ化した後、@Overload
javac.exeを使用してクラスを作成し、それを使用してコンパイルします。
import gearon.customAnnotation.Overload;
public class OverloadTest {
@Overload
public static void foo(){
}
@Overload
public static void foo(String s){
}
@Overload
public static void nonOverloadedMethod(){
}
}
以来nonOverloadedMethod()
、実際にオーバーロードされていない、私たちは以下のような出力が得られます。
OverloadProcessor::process
なぜentry.getValue() == 1
ですか?親クラス/インターフェースに注釈を追加する必要roundEnv.getElementsAnnotatedWith(Overload.class)
がないので、親クラス/インターフェースを取得しませんか?
ここにあります@Override
:http : //www.docjar.com/html/api/java/lang/Override.java.html。
自分で書くかもしれない注釈と区別する特別なことは何もありません。興味深い部分は、注釈の消費者にあります。のようなアノテーションの場合@Override
、それはJavaコンパイラ自体、静的コード分析ツール、またはIDEにあります。
@Override
(または他の標準アノテーション)を実際に作成することはできません。
私も同じ質問の答えを探していました。以下のリンクは、注釈の内部を取得するための統合された優れたものを提供しました。https://dzone.com/articles/how-annotations-work-java よろしくお願いします!