Javaアノテーション
Javaコンピュータプログラミング言語において、アノテーションは属性のようにJavaソースコードに追加できる構文メタデータの一種である。[1]クラス、メソッド、変数、パラメータ、Javaパッケージにアノテーションを付けることができる。Javadocタグと同様に、Javaアノテーションはソースファイルから読み取ることができる。Javadocタグとは異なり、JavaアノテーションはJavaコンパイラによって生成されたJavaクラスファイルに埋め込み、そこから読み取ることもできる。これにより、アノテーションは実行時にJava仮想マシンによって保持され、リフレクションを介して読み取ることができる。[2] Javaでは、既存のアノテーションからメタアノテーションを作成することが可能である。[3]
歴史
Javaプラットフォームには、様々なアドホックなアノテーション機構(例えば、transient修飾子や@Deprecatedjavadocタグなど)があります。Java仕様要求JSR-175は、2002年にJavaコミュニティプロセスに汎用アノテーション(メタデータとも呼ばれる)機能を導入し、2004年9月に承認されました。[4]
Java開発キット(JDK)バージョン1.5以降、言語自体にアノテーションが利用可能になりました。JDKバージョン1.5では、aptツールがコンパイル時のアノテーション処理のための暫定インターフェースを提供していました。これはJSR-269で正式に規定され、バージョン1.6ではjavacコンパイラに統合されました。
C++26では、C++にJava アノテーションに似たリフレクション用のアノテーションが追加されました。
組み込みの注釈
Javaは言語に組み込まれた一連のアノテーションを定義しています。7つの標準アノテーションのうち、3つはjava.langに含まれており、残りの4つはjava.langからインポートされていますjava.lang.annotation。[5] [6]
| 注釈 | パッケージ | 説明 |
|---|---|---|
@Deprecated | java.lang | メソッドを廃止としてマークします。メソッドが使用されている場合はコンパイル警告が発生します。 |
@FunctionalInterface | java.lang | インターフェイスを機能インターフェイスとしてマークします。 |
@Override | java.lang | メソッドが祖先クラスで定義されたメソッドをオーバーライドすることを示します。メソッドが親クラスまたは実装されたインターフェースのいずれにも見つからない場合、コンパイルエラーが発生します。 |
@SafeVarargs | java.lang | Java 7 以降、ジェネリック varargsパラメータを持つメソッドまたはコンストラクターのすべての呼び出し元に対する警告を抑制します。 |
@SuppressWarnings | java.lang | 注釈パラメータで指定されたコンパイル時の警告を抑制するようにコンパイラに指示します。 |
@Documented | java.lang.annotation | ドキュメントに含める別の注釈をマークします。 |
@Inherited | java.lang.annotation | 注釈が付けられたクラスのサブクラスに継承される別の注釈をマークします (デフォルトでは注釈はサブクラスに継承されません)。 |
@Native | java.lang.annotation | 定数値を定義するフィールドを、ネイティブ コードから参照される可能性があるものとしてマークします。 |
@Repeatable | java.lang.annotation | 別の注釈を繰り返し可能としてマークします。 |
@Retention | java.lang.annotation | マークされた注釈がどのように保存されるか (コードのみ、クラスにコンパイルされるか、またはリフレクションを通じて実行時に使用可能か) を指定します。 |
@Target | java.lang.annotation | 別の注釈をマークして、注釈を適用できる Java 要素の種類を制限します。 |
Jakarta EE (旧称Java Platform, Enterprise Edition)では、以下のアノテーションも存在しますjakarta.annotation(旧称javax.annotation): [7] [8]
| 注釈 | パッケージ | 説明 |
|---|---|---|
@Generated | jakarta.annotation | 生成されたソース コード (つまり、ユーザーによって記述されたものではなく、コンピューターによって自動的に生成されたものでもない) をマークします。 |
@Resource | jakarta.annotation | クラス、メソッド、またはフィールドをリソースへの参照としてマークします。 |
@Resources | jakarta.annotation | 複数のリソース宣言のコンテナとして、リソースへの参照を宣言します。 |
@PostConstruct | jakarta.annotation | 依存性注入後に初期化を実行するためにメソッドを実行する必要があることを示すためにメソッドをマークします。つまり、クラスが使用される前にメソッドを呼び出す必要があります。 |
@PreDestroy | jakarta.annotation | メソッドをコールバック通知としてマークし、インスタンスがコンテナによって削除中であることを示します。つまり、メソッドはインスタンスによって保持されているリソースを解放するために使用されます。 |
@Priority | jakarta.annotation | プログラム要素をマークして、使用する順序を示します。 |
@Nonnull | jakarta.annotation | できない要素をマークしますnull。 |
@Nullable | jakarta.annotation | である可能性が明示的にある要素をマークしますnull。 |
@RunAs | jakarta.annotation | Jakarta EE コンテナでの実行中のアプリケーションのセキュリティ ロールを定義します。 |
@RolesAllowed | jakarta.annotation.security | メソッドにマークを付けて、そのメソッドへのアクセスが許可されるセキュリティ ロールを指定します。 |
@PermitAll | jakarta.annotation.security | メソッドをマークして、すべてのセキュリティ ロールがメソッドにアクセスできるように指定します。 |
@DenyAll | jakarta.annotation.security | メソッドにマークを付けて、セキュリティ ロールがメソッドにアクセスできないように指定します。 |
@DeclareRoles | jakarta.annotation.security | アプリケーションで使用されるセキュリティ ロールを指定します。 |
@DataSourceDefinition | jakarta.annotation.sql | Java Naming and Directory Interface (JNDI)DataSourceに登録されるコンテナーを定義します。 |
@DataSourceDefinitions | jakarta.annotation.sql | DataSource複数のデータ ソース宣言のコンテナーとして機能するコンテナーを宣言します。 |
以前は にアノテーション があり、@ManagedBeanこれjakarta.annotationはリソース注入、ライフサイクルコールバック、インターセプターといった基本的なサービス群をサポートするコンテナ管理オブジェクトであるマネージドBeanを宣言するために使用されていました。しかし、これは削除されました。[9] [10]
例
組み込みの注釈
この例は、アノテーションの使用方法を示しています@Override。コンパイラーは、親クラスで一致するメソッドをチェックします。この場合、gettype()Catクラスのメソッドが実際にはAnimalクラスをオーバーライドしていないため、ケースの不一致getType()によりエラーが発生します。アノテーションがない場合、Catクラスにnameという新しいメソッドが作成されます。@Overridegettype()
パブリッククラスAnimal { public void speak () {} public String getType () { return "Generic animal" ; } } public class Cat extends Animal { @Override public void speak () { //これは良いオーバーライドです。System.out.println ( " Meow ." ); } @Override public String gettype () { // タイプミスによるコンパイル時エラー: gettype() ではなく getType() とする必要があります。return "Cat" ; } } カスタム注釈
アノテーション型宣言は通常のインターフェース宣言と同様です。キーワード「interface」の前にアットマーク(@)を付けます。
// @Twizzle はメソッド toggle() へのアノテーションです。@ツイズルパブリックvoidトグル() { }// アノテーション Twizzle を宣言します。パブリック@interface Twizzle { }アノテーションには、アノテーション型のメソッドとしてモデル化されたキーと値のペアのセットを含めることができます。各メソッド宣言は、アノテーション型の要素を定義します。メソッド宣言には、パラメータやthrows句を含めることはできません。戻り値の型は、プリミティブ、文字列、クラス、列挙型、アノテーション、および前述の型の配列に制限されます。メソッドはデフォルト値を持つことができます。
// 同じ: @Edible(value = true)@食べられる( true )アイテムitem = new Carrot (); パブリック@interface Edible { ブール値()デフォルトはfalse ; }@Author ( first = "ウンパ" 、last = "ルンパ" ) Book book =新しいBook (); パブリック@interface Author { 文字列first (); 文字列last (); }注釈自体に注釈を付けて、いつどこで使用できるかを示すことができます。
@Retention ( RetentionPolicy . RUNTIME ) // リフレクションを介して実行時にこのアノテーションにアクセスできるようにします。 @Target ({ ElementType . METHOD }) // このアノテーションはクラスメソッドにのみ適用できます。 パブリック@interface Tweezable {} コンパイラは、構文上の目的で一連の特別な注釈 (、および を含む) を予約し@Deprecatedます@Override。@SuppressWarnings
アノテーションは、外部ソース(XML設定ファイルなど)やプログラム(API呼び出しなど)で宣言する必要があるユーザー定義のクラスやメソッドに、動作を簡単に適用する手段としてフレームワークでよく使用されます。例えば、以下はアノテーション付きのJPAデータクラスです。
@Entity // これをエンティティBeanとして宣言します @Table ( name = "people" ) // BeanをSQLテーブル "people"にマッピングします パブリッククラスPersonはSerializableを実装します{ @Id // これを主キー列にマップします。 @GeneratedValue ( strategy = GenerationType . AUTO ) // 新しい主キーは私たちではなくデータベースによって生成されます。 プライベート整数ID ; @Column ( length = 32 ) // 列の値を 32 文字に切り捨てます。 プライベート文字列名; パブリック整数getId () { idを返します。 } パブリックvoid setId (整数ID ) { this .id = id ; } パブリック文字列 getName () { 名前を返します。 } public void setName (文字列名) { this .name =名前; }}アノテーションはメソッド呼び出しではなく、それ自体では何も行いません。クラスオブジェクトは実行時にJPA実装に渡され、JPA実装はアノテーションを抽出してオブジェクト・リレーショナル・マッピングを生成します。
完全な例を以下に示します。
パッケージcom.acme.proj.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をインポートします。 @文書化済み@Retention (保持ポリシー. RUNTIME )@ターゲット({ ElementType.TYPE 、ElementType.METHOD 、 ElementType.CONSTRUCTOR 、ElementType.ANNOTATION_TYPE 、 ElementType.PACKAGE 、ElementType.FIELD 、ElementType.LOCAL_VARIABLE })@継承パブリック@interface未完成{ パブリック列挙型優先度{ LOW 、MEDIUM 、HIGH } 文字列値(); 文字列[] changedBy ()デフォルト"" ; 文字列[] lastChangedBy ()デフォルト"" ; 優先度priority ()デフォルトの優先度.MEDIUM ; 文字列createdBy ()デフォルトは"James Gosling" ; 文字列lastChanged ()デフォルト"2011-07-08" ; }パッケージcom.acme.proj.annotation ; パブリック@interface建設中{ 文字列の所有者()デフォルトは"Patrick Naughton" ; 文字列値()デフォルトは「オブジェクトは構築中です。」; 文字列createdBy ()デフォルト"Mike Sheridan" ; 文字列lastChanged ()デフォルト"2011-07-08" ; }パッケージcom.acme.proj.validators ; javax.faces.application.FacesMessageをインポートします。 javax.faces.component.UIComponentをインポートします。 javax.faces.context.FacesContextをインポートします。 javax.faces.validator.Validatorをインポートします。 javax.faces.validator.ValidatorExceptionをインポートします。 com.acme.proj.annotation.UnderConstructionをインポートします。 com.acme.proj.annotation.Unfinishedをインポートします。 com.acme.proj.annotation.Unfinished.Priorityをインポートします。 com.acme.proj.util.Utilをインポートします。 @UnderConstruction (所有者= "Jon Doe " ) パブリッククラスDateValidator はValidatorを実装します{ public void検証( FacesContextコンテキスト、UIComponentコンポーネント、オブジェクト値)はValidatorExceptionをスローします{ 文字列日付= (文字列)値; String errorLabel = "有効な日付を入力してください。" ; if ( !コンポーネント. getAttributes (). isEmpty ()) { errorLabel = (文字列)コンポーネント.getAttributes ( ). get ( "errordisplayval" ); } if ( ! Util.validateAGivenDate (日付) ) { @未完成( changedBy = "スティーブ" 、 value = "コンテキストにメッセージを追加するかどうかの確認" 、 優先度=優先度.高 ) FacesMessageメッセージ=新しいFacesMessage (); メッセージ.setSeverity ( FacesMessage.SEVERITY_ERROR ) ; メッセージ.setSummary ( errorLabel ) ; メッセージ。setDetail (エラーラベル); 新しいValidatorException ( message )をスローします。 } }}処理
Javaソースコードをコンパイルすると、アノテーションはアノテーションプロセッサと呼ばれるコンパイラプラグインによって処理されます。プロセッサは情報メッセージを生成したり、追加のJavaソースファイルやリソースを作成したりすることができ、これらはコンパイルおよび処理されます。ただし、アノテーションプロセッサはアノテーション付きコード自体を変更することはできません(コードの変更は、Java言語仕様に規定されていない方法を使用して実装できます)。Javaコンパイラは、アノテーションにまたは がある場合、RetentionPolicy条件付きでアノテーションメタデータをクラスファイルに保存します。その後、JVMやその他のプログラムは、このメタデータを参照して、プログラム要素とのやり取り方法や動作の変更方法を決定できます。CLASSRUNTIME
Javaプログラマは、アノテーションプロセッサを用いてアノテーションを処理するだけでなく、リフレクションを用いてアノテーションを処理する独自のコードを作成することもできます。Java SE 5は、パッケージで定義された新しいインタフェースをサポートしています。このパッケージには、、、、、、などのJavaリフレクションクラスによって実装される、java.lang.reflectというインタフェースが含まれています。このインタフェースの実装は、Java仮想マシンで現在実行中のプログラムのアノテーション付き要素を表すために使用されます。このインタフェースにより、アノテーションをリフレクションで読み取ることができます。AnnotatedElementClassConstructorFieldMethodPackage
インターフェースは、保持期間AnnotatedElementを持つアノテーションへのアクセスを提供しますRUNTIME。このアクセスはgetAnnotation、、、getAnnotationsおよびisAnnotationPresentメソッドによって提供されます。アノテーション型はクラスと同様にコンパイルされ、バイトコードファイルに保存されるため、これらのメソッドによって返されるアノテーションは、通常のJavaオブジェクトと同様にクエリできます。アノテーション処理の完全な例を以下に示します。
java.lang.annotation.Retentionをインポートします。java.lang.annotation.RetentionPolicyをインポートします。 // これは処理される注釈です// ターゲットのデフォルトはすべての 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要素の値:% n " ) ; if ( element.isAnnotationPresent ( TypeHeader.class ) ) { // getAnnotationはAnnotation型を返しますAnnotation singleAnnotation = element.getAnnotation ( TypeHeader.class ) ; TypeHeader header = ( TypeHeader ) singleAnnotation ; System.out.printf ( "開発者: %s%n" 、header.developer ( ) ) ; System.out.printf ( "最終更新日時:%s%n " 、header.lastModified ( ) ) ; // teamMembersはString []として返されますSystem.out.print ( "チームメンバー:" ) ; for ( Stringmember : header.teamMembers ( ) ) { System.out.printf ( " % s , " , member ) ; } System.out.println ( ) ; System.out.println ( "人生の意味: % s %n " 、header.meaningOfLife ( ) ) ; } } catch (例外exception ) { exception.printStackTrace ( ) ; } } } 参照
- ジャカルタ注釈
- CLI属性
- ジャワ
- Java仮想マシン
- モデル駆動型アーキテクチャ
- Python デコレータはJava アノテーションにヒントを得たもので、同様の構文を持ちます。
参考文献
- ^ “Annotations”. 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月2日). 「JSR 175: JavaTMプログラミング言語のメタデータ機能」. Java Community Process . 2008年3月5日閲覧。
- ^ 「定義済みアノテーション型」Oracle Corporation . 2016年12月17日閲覧。
- ^ 「組み込みアノテーション:標準アノテーション」 。 2016年12月17日閲覧。
- ^ "Jakarta Annotations API 1.3.5 API".ジャカルタEE 。2025 年 8 月 13 日に取得。
- ^ 「ジャカルタの注釈」。ジャカルタEE 。2025 年 8 月 13 日に取得。
- ^ "Jakarta Annotations API 1.3.5 API".ジャカルタEE 。2025 年 8 月 13 日に取得。
- ^ 「ジャカルタの注釈」。ジャカルタEE 。2025 年 8 月 13 日に取得。
外部リンク
- Sun Developer Network サイトの Java 6 アノテーション入門
- Javaアノテーション入門 MM Islam Chisty著 2017年3月28日アーカイブWayback Machine
- 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 .