Javaプログラミング言語では、注釈はJavaソースコードに追加できる構文メタデータの一種です。[1]クラス、メソッド、変数、パラメータ、Javaパッケージに注釈を付けることができます。Javadocタグと同様に、Java注釈はソースファイルから読み取ることができます。Javadocタグとは異なり、Java注釈はJavaコンパイラによって生成されたJavaクラスファイルに埋め込んで読み取ることもできます。これにより、注釈は実行時にJava仮想マシンによって保持され、リフレクションを介して読み取ることができます。[2] Javaの既存の注釈からメタ注釈を作成することができます。[3]
歴史
Javaプラットフォームには、修飾子やjavadocタグなど、さまざまなアドホック注釈メカニズムがあります。Java仕様要求JSR-175は、2002年にJavaコミュニティプロセスに汎用注釈(メタデータとも呼ばれる)機能を導入し、2004年9月に承認されました。[4]transient@Deprecated
Java Development Kit (JDK)のバージョン 1.5 から、言語自体で注釈が利用できるようになりました。このaptツールは、JDK バージョン 1.5 でコンパイル時の注釈処理用の暫定インターフェイスを提供しました。JSR-269 でこれが正式化され、バージョン 1.6 で
javacコンパイラに統合されました。
組み込みの注釈
Javaは言語に組み込まれた一連の注釈を定義しています。7つの標準注釈のうち3つはjava.langの一部であり、残りの4つはjava.lang.annotationからインポートされています。[5] [6]
Java コードに適用される注釈:
@Override— メソッドがオーバーライドであるかどうかを確認します。メソッドが親クラスまたは実装されたインターフェースのいずれかに見つからない場合は、コンパイル エラーが発生します。@Deprecated— メソッドを廃止としてマークします。メソッドが使用されている場合はコンパイル警告が発生します。@SuppressWarnings—アノテーション パラメータで指定されたコンパイル時の警告を抑制するようにコンパイラに指示します。
他の注釈に適用される注釈 (「メタ注釈」とも呼ばれます):
@Retention— マークされた注釈がコードのみに格納されるか、クラスにコンパイルされるか、またはリフレクションを通じて実行時に使用可能になるかを指定します。@Documented— ドキュメントに含める別の注釈をマークします。@Target— 別の注釈をマークして、注釈を適用できる Java 要素の種類を制限します。@Inherited— 注釈付きクラスのサブクラスに継承される別の注釈をマークします (デフォルトでは注釈はサブクラスに継承されません)。
Java 7 以降、言語に 3 つの追加の注釈が追加されました。
@SafeVarargs— Java 7 以降、ジェネリック変数 引数パラメータを持つメソッドまたはコンストラクターのすべての呼び出し元に対する警告を抑制します。@FunctionalInterface— Java 8 以降、型宣言が関数インターフェースとなることを指定します。@Repeatable— Java 8 以降、同じ宣言にアノテーションを複数回適用できることを指定します。
例
組み込みの注釈
この例は、アノテーションの使用方法を示しています@Override。これは、コンパイラーに、親クラスで一致するメソッドをチェックするように指示します。この場合、ケースが一致しないため、クラス Cat のメソッドが実際にはクラス Animal を期待どおりにgettype()オーバーライドしないため、エラーが生成されます。アノテーションがない場合、クラス Cat に name の新しいメソッドが作成されます。
getType()@Overridegettype()
パブリッククラスAnimal {パブリックvoid話す() { }
public String getType () { return "Generic animal" ; } }
public class Cat extends Animal { @Override public void talk () { //これは適切なオーバーライドです。System.out.println ( " Meow." ) ; }
@Override
public String gettype () { // タイプミスによるコンパイル時エラー: gettype() ではなく getType() にする必要があります。return "Cat" ; } }
カスタム注釈
注釈型宣言は通常のインターフェース宣言に似ています。アットマーク (@) がキーワード「 interface」の前に付きます。
// @Twizzle はメソッドtoggle() へのアノテーションです。
@Twizzle public void toggle () { }
// アノテーション Twizzle を宣言します
。public @interface Twizzle { }
アノテーションには、アノテーション タイプのメソッドとしてモデル化されるキーと値のペアのセットを含めることができます。各メソッド宣言は、アノテーション タイプの要素を定義します。メソッド宣言には、パラメーターや throws 句を含めることはできません。戻り値の型は、プリミティブ、文字列、クラス、列挙型、アノテーション、および前述の型の配列に制限されます。メソッドには既定値を設定できます。
// 次と同じです: @Edible(value = true)
@Edible ( true ) Item item = new Carrot ();
パブリック@interface Edible {ブール値()デフォルトfalse ; }
@Author ( first = "Oompah" 、last = "Loompah" ) Book book = new Book ();
パブリック@interface Author {文字列first ();文字列last (); }
注釈自体に注釈を付けて、いつどこで使用できるかを示すことができます。
@Retention ( RetentionPolicy . RUNTIME ) // このアノテーションをリフレクションを介して実行時にアクセスできるようにします。@Target ({ ElementType . METHOD }) // このアノテーションはクラスメソッドにのみ適用できます。public @interface Tweezable { }
コンパイラは、構文上の目的で
一連の特別な注釈 ( @Deprecated、@Overrideおよびを含む) を予約します。@SuppressWarnings
アノテーションは、外部ソース (XML 構成ファイルなど) またはプログラム (API 呼び出しを使用) で宣言する必要があるユーザー定義のクラスやメソッドに動作を簡単に適用する方法として、フレームワークでよく使用されます。たとえば、以下はアノテーションが付けられたJPAデータ クラスです。
@Entity // これをエンティティ Bean として宣言します@Table ( name = "people" ) // Bean を SQL テーブル "people" にマップしますpublic class Person implements Serializable { @Id // これを主キー列にマップします。@GeneratedValue ( strategy = GenerationType . AUTO ) // 新しい主キーは私たちではなく、データベースによって生成されます。private Integer id ;
@Column ( length = 32 ) // 列の値を 32 文字に切り捨てます。private String name ;
パブリック整数getId () {戻り値 id ; }
パブリックvoid setId (整数id ) { this . id = id ; }
パブリック文字列getName () {戻り値 name ; }
public void setName ( String name ) { this . name = name ; } }
アノテーションはメソッド呼び出しではなく、それ自体では何も行いません。代わりに、クラス オブジェクトが実行時にJPA実装に渡され、JPA 実装がアノテーションを抽出してオブジェクト リレーショナル マッピングを生成します。
完全な例を以下に示します。
パッケージcom.annotation ;
java.lang.annotation.Documentedをインポートします。java.lang.annotation.ElementTypeをインポートします。java.lang.annotation.Inheritedをインポートします。java.lang.annotation.Retentionをインポートします。java.lang.annotation.RetentionPolicyをインポートします。java.lang.annotation.Targetをインポートします。
@Documented
@Retention ( RetentionPolicy . RUNTIME )
@Target ({ ElementType . TYPE 、ElementType . METHOD 、
ElementType . CONSTRUCTOR 、ElementType . ANNOTATION_TYPE 、ElementType . PACKAGE 、ElementType . FIELD 、ElementType . LOCAL_VARIABLE }) @Inherited
public @interface Unfinished { public enum Priority { LOW , MEDIUM , HIGH } String value (); String [] changedBy () default "" ; String [] lastChangedBy () default "" ; Priority priority () default Priority . MEDIUM ; String createdBy () default "James Gosling" ; String lastChanged () default "2011-07-08" ; }
パッケージcom.annotation ;
public @interface UnderConstruction { String owner () default "Patrick Naughton" ; String value () default "オブジェクトは現在構築中です。" ; String createdBy () default "Mike Sheridan" ; String lastChanged () default "2011-07-08" ; }
パッケージcom.validators ;
javax.faces.application.FacesMessageをインポートします。javax.faces.component.UIComponentをインポートします。javax.faces.context.FacesContextをインポートします。javax.faces.validator.Validatorをインポートします。javax.faces.validator.ValidatorExceptionをインポートします。
com.annotation.UnderConstructionをインポートします。com.annotation.Unfinishedをインポートします。com.annotation.Unfinished.Priorityをインポートします。com.util.Utilをインポートします。
@UnderConstruction (所有者= "Jon Doe" )
publicクラスDateValidator はValidatorを実装します{ public void valid ( FacesContext context 、UIComponent component 、Object value ) throws ValidatorException { String date = ( String ) value ; String errorLabel = "有効な日付を入力してください。" ; if ( ! component . getAttributes (). isEmpty ()) { errorLabel = ( String ) component . getAttributes (). get ( "errordisplayval" ); }
if ( ! Util.validateAGivenDate ( date )) { @Unfinished ( changedBy = " Steve" , value = "メッセージをコンテキストに追加するかどうかを確認します" , priority = Priority.HIGH ) FacesMessage message = new FacesMessage ( ) ; message.setSeverity ( FacesMessage.SEVERITY_ERROR ) ; message.setSummary ( errorLabel ) ; message.setDetail ( errorLabel ) ; throw new ValidatorException ( message ) ; } } }
処理
Java ソース コードをコンパイルすると、アノテーションはアノテーション プロセッサと呼ばれるコンパイラ プラグインによって処理されます。プロセッサは情報メッセージを生成したり、追加の Java ソース ファイルやリソースを作成したりすることができ、これらはコンパイルされて処理されます。ただし、アノテーション プロセッサはアノテーション付きコード自体を変更することはできません (コードの変更は、Java 言語仕様以外の方法を使用して実装できます)。アノテーションにまたは がRetentionPolicyある場合、Java コンパイラは条件付きでアノテーション メタデータをクラス ファイルに保存します。その後、JVMまたは他のプログラムはメタデータを検索して、プログラム要素と対話する方法やその動作を変更する方法を決定できます。
CLASSRUNTIME
Java プログラマーは、注釈プロセッサを使用して注釈を処理するだけでなく、リフレクションを使用して注釈を処理する独自のコードも作成できます。Java SE 5 は、パッケージで定義されている新しいインターフェースをサポートしますjava.lang.reflect。このパッケージには、、、、、およびを含む Java リフレクション クラスによって実装される、というインターフェースが含まれています。このAnnotatedElementインターフェースの実装は、Java 仮想マシンで現在実行されているプログラムの注釈付き要素を表すために使用されます。このインターフェースにより、注釈をリフレクションで読み取ることができます。
ClassConstructorFieldMethodPackage
インターフェースは、保持期間AnnotatedElementを持つ注釈へのアクセスを提供しますRUNTIME。このアクセスはgetAnnotation、、、getAnnotationsおよびisAnnotationPresentメソッドによって提供されます。注釈型はクラスと同様にコンパイルされ、バイトコード ファイルに保存されるため、これらのメソッドによって返される注釈は、通常の Java オブジェクトと同様に照会できます。注釈を処理する完全な例を以下に示します。
java.lang.annotation.Retentionをインポートします。java.lang.annotation.RetentionPolicyをインポートします。
// これは処理される注釈です
// Target のデフォルトはすべての Java 要素です
// 保持ポリシーを RUNTIME に変更します (デフォルトは CLASS)
@Retention ( RetentionPolicy . RUNTIME )
public @interface TypeHeader { // 開発者属性に指定されたデフォルト値String developer () default "Unknown" ; String lastModified (); String [] teamMembers (); int meaningOfLife (); }
// これはクラスに適用される注釈です
@TypeHeader ( developer = "Bob Bee" 、lastModified = "2013-02-12" 、teamMembers = { "Ann" 、"Dan" 、"Fran" }、meaningOfLife = 42 )
public class SetCustomAnnotation { // クラスの内容はここに記述します}
// これは注釈を処理するサンプルコードです
import java.lang.annotation.Annotation ; import java.lang.reflect.AnnotatedElement ;
パブリッククラスUseCustomAnnotation {パブリック静的void main ( String [] args ) {クラス< SetCustomAnnotation > classObject = SetCustomAnnotation . class ; readAnnotation ( classObject ); }
static void readAnnotation ( AnnotatedElement element ) { try { System.out.println ( " Annotation element values: \n" ) ; if ( element.isAnnotationPresent ( TypeHeader.class ) ) { // getAnnotationはAnnotation型を返しますAnnotation singleAnnotation = element.getAnnotation ( TypeHeader.class ) ; TypeHeader header = ( TypeHeader ) singleAnnotation ;
System.out.println ( "開発者: " + header.developer ( ) ); System.out.println ( "最終更新日:" + header.lastModified () ) ;
// teamMembersはString [] として返されますSystem.out.print ( "チームメンバー: " ) ; for ( String member : header.teamMembers ( ) ) System.out.print ( member + " , " ) ; System.out.print ( " \ n" ) ;
System.out.println ( "人生の意味:" + header.meaningOfLife ( ) ) ; } } catch (例外exception ) { exception.printStackTrace ( ) ; } } }
参照
- ジャカルタ注釈
- CLI 属性
- ジャワ
- Java仮想マシン
- モデル駆動型アーキテクチャ
- Python デコレータは、Java アノテーションにヒントを得たもので、同様の構文を持ちます。
参考文献
- ^ 「注釈」。Sun Microsystems。2011年9月25日時点のオリジナルよりアーカイブ。2011年9月30日閲覧。。
- ^ Sun Microsystems (2005). Java(TM) 言語仕様 (第 3 版). Prentice Hall . ISBN 0-321-24678-0。。
- ^ Dare Obasanjo (2007)。「Microsoft の C# プログラミング言語と Sun Microsystems の Java プログラミング言語の比較: メタデータ注釈」。Dare Obasanjo。2012 年 9 月 19 日時点のオリジナルよりアーカイブ。2012年 9 月 20 日閲覧。
- ^ Coward, Danny (2006-11-02). 「JSR 175: JavaTM プログラミング言語のメタデータ機能」. Java コミュニティ プロセス. 2008-03-05に取得。
- ^ 「定義済み注釈タイプ」。Oracle Corporation 。 2016年12月17日閲覧。
- ^ 「組み込み注釈: 標準注釈」 。2016年 12 月 17 日閲覧。
外部リンク
- Sun Developer Network サイトの Java 6 アノテーションの紹介
- Java アノテーション入門 (MM Islam Chisty 著)
- Srinivasan, Krishna (2007 年 8 月 11 日)。「Java 5.0 の注釈」。JavaBeat。2015年5 月 31 日時点のオリジナルよりアーカイブ。
- Hunt, John (2006 年 2 月 24 日)。「Java アノテーションについて」。The Register。
- 「Java でカスタム注釈を作成して実装する方法」。So Many Word。2014年 2 月 15 日。2014 年 2 月 23 日のオリジナルからアーカイブ。
- 「Java アノテーション チュートリアル (例付き)」。TutorialsDesk。2014年 10 月 9 日。
- Thakor, Vicky (2015 年 10 月 13 日)。「Java のアノテーションを理解する」。例による Java。
