Javaの「アノテーション」は、ソースコードに「注釈」をつけるための機能です。アノテーションを活用することで、誤った記述・好ましくない記述に対してコンパイルエラーや警告が出せます。結果的に、より安全で効率的なプログラムが書きやすくなります。
しかし、アノテーションは必ずしも使わないといけない機能ではないので、「馴染みがない」「どんな機能かわからない」という人も多いはず。アノテーションにはさまざまな種類があり、自分でオリジナルのアノテーションも作成できるので、非常に便利な機能です。
そこで本記事では、Javaのアノテーションの使い方や作成方法、具体的な活用テクニックなどについて解説します。アノテーションに慣れていない人は、ぜひ参考にしてください。
目次
Javaの「アノテーション」とは、ソースコードに付け加える「注釈」のことです。「@」から始まるラベルのようなもので、クラス・インターフェース・フィールド・メソッドなどの「宣言の先頭」につけます。アノテーションの代表例は以下のようなものです。
@Override // 「Override」アノテーション public void method() { // 以下略 }
アノテーションは、プログラムのロジックそのものとは直接関係がない、「情報」や「説明」を明示できる機能です。なお、注釈というと「コメント」を思い浮かべるかもしれませんが、コメントには「そのとおりに書きなさい」という強制力はいっさいありません。
アノテーションでは、クラスやメソッドの名前を間違えたときや、好ましくない書き方をしたときに「コンパイルエラー」や「警告」を出せます。その結果、正確なプログラムを書きやすくなるため、効率を重視する実務では積極的に活用されています。
アノテーションを使うことで得られる最も大きなメリットは、プログラミングのミスを予防できることです。プログラミングでは、ミスが多々発生します。コンパイルエラーが出るミスなら問題ありませんが、構文上の誤りがない場合はコンパイルが通り、実行時に思わぬエラーやバグの原因になることがあります。
アノテーションを活用すると、記述ミスや好ましくないソースコードに対して、エラーや警告を出力できるので、バグやエラーを予防可能です。また、アノテーションではコードの書き方を制限できるため、複数人で開発する現場で「意思統一」を図りやすくなります。ソースコード上でコミュニケーションが取れるので、開発効率が向上します。
Javaのアノテーションには、さまざまな種類があります。しかし、一般的に使われる「標準アノテーション」は、以下5種類しかありません。本章では、それぞれの機能と具体的な使い方を、サンプルコードを交えて解説します。
アノテーション | 概要 |
---|---|
@Override | スーパークラスのメソッドをオーバーライドすることを宣言する |
@Deprecated | クラスやメソッドが「非推奨」であることを宣言する |
@SuppressWarnings | コンパイラの不要な警告を抑制する |
@SafeVarargs | 可変長引数のデータ型の安全性を保障する |
@FunctionalInterface | 関数型インターフェースとして定義することを宣言する |
「@Override」は、「スーパークラスのメソッドをオーバーライドする」ことを示すアノテーションです。対象となるメソッドが、スーパークラスのメソッドをオーバーライドしていることを保障し、正しくオーバーライドできていない場合はコンパイルエラーとなります。@Overrideアノテーションの使い方を、以下のサンプルコードで確認しましょう。
//サンプルプログラム
class SuperClass { public void method(String string) { System.out.println("スーパークラスのメソッド" + string); } } class SubClass extends SuperClass { // 「Override」アノテーションを活用し、 // スーパークラスのメソッドをオーバーライドしたことを宣言する @Override public void method(String string) { System.out.println("基底クラスのメソッド" + string); } } public class Main { public static void main(String[] args) { // サブクラスをインスタンス化する SubClass sub = new SubClass(); // サブクラスの「method」を実行する sub.method("テスト"); } }
//実行結果
基底クラスのメソッドテスト
アクセス修飾子・戻り値の型・メソッド名・引数など、どれかひとつでも間違っている場合はコンパイルエラーとなるため、対象メソッドを確実にオーバーライドできます。なお、オーバーライドではないメソッドに「@Override」アノテーションを付けた場合も、コンパイルエラーとなります。
「@Deprecated」は、「クラスやメソッドが非推奨である」ことを示すアノテーションです。たとえば大規模プロジェクトの場合は、処理内容が好ましくないクラス・メソッドがあるものの、互換性のために残すことがあります。しかし、「どうしても必要なとき以外は使ってほしくない」という場合、@Deprecatedアノテーションが役立ちます。
// クラスを「非推奨」にする @Deprecated(since="バージョン") // 「バージョン」には数値を指定する class Test { // 以下略 } // メソッドを「非推奨」にする @Deprecated(since="バージョン") // 「バージョン」には数値を指定する public void method() { // 以下略 }
@Deprecatedアノテーションは、コンパイルエラーではなく警告を出すので、ほかのプログラマーに代替のクラスやメソッドの使用を促すことができます。@Deprecatedアノテーションの使い方を、以下のサンプルコードで確認しましょう。
//サンプルプログラム
// クラスを「非推奨」にする @Deprecated(since = "8") class Test { // メソッドを「非推奨」にする @Deprecated(since = "9") public void method() { System.out.println("非推奨のメソッド実行"); } } public class Main { public static void main(String[] args) { // テストクラスをインスタンス化する Test test = new Test(); // テストクラスの「method」を実行する test.method(); } }
//実行結果
非推奨のメソッド実行
以上のように、@Deprecatedアノテーションが付与されたクラスやメソッドを使っても、コンパイルエラーは出ず通常どおり実行できます。ただし、非推奨であることを示す警告が表示されるため、プログラマー同士のコミュニケーションに効果的です。
なお「Eclipse」をIDEとして使っている場合は、@Deprecatedアノテーションが付与されているクラスやメソッドに、上記画像のような「打ち消し線」が表示されます。そのため、ほかのプログラマーが見ても明らかに「非推奨」だとわかり、クラスやメソッドの使用を抑制できます。
「@SuppressWarnings」は、「コンパイラの不要な警告を抑制する」ためのアノテーションです。Javaのコンパイラは、安全なプログラミングをサポートするために、さまざまな警告を出します。しかし、コンパイラが不要な警告を出すときや、意図して警告が出るようなコードを書いているときなどは、こうした警告は邪魔になってしまいます。
余計な警告は無視するものですが、それが多すぎると「本当に重要な警告」を見逃してしまいかねません。@SuppressWarningsアノテーションを使うことで、重要な警告に注目しやすくなります。@SuppressWarningsアノテーションは以下のように使います。
@SuppressWarnings("警告名") // 「警告名」には後述する既定値を指定する // 以下、警告対象のメソッドやクラス
たとえば、メソッドに未使用のローカル変数がある場合は、コンパイラは「ローカル変数が使用されていません」という警告を表示します。しかし、将来的にメソッドを拡張するために、あえて未使用の変数を残すケースは多いです。そこで以下のサンプルコードのように、@SuppressWarningsアノテーションを活用して、余計な警告を抑制しましょう。
//サンプルプログラム
class Test { public void method() { // 変数「i」は未使用だが、将来的な拡張のために残しておきたい。 // しかし、そのままでは不要な警告が出るので、 // 「@SuppressWarnings("unused")」で「未使用変数」の警告を抑制する。 @SuppressWarnings("unused") int i; } } public class Main { public static void main(String[] args) { // テストクラスをインスタンス化する Test test = new Test(); // テストクラスの「method」を実行する test.method(); } }
//実行結果
以下の画像のように、「int i;」の部分に警告が表示されなくなります。
Eclipseの場合は、警告が出た部分はコードエディター上で「波線」が表示されます。未使用変数の警告名は「unused」なので、今回は「@SuppressWarnings(“unused”)」と記述すればOK。ちなみに、主な警告名には以下のようなものがあります。
警告名 | 意味 | アノテーション |
---|---|---|
cast | 不要なキャストを行っている | @SuppressWarnings(“cast”) |
deprecation | 非推奨のクラスやメソッドを使用している | @SuppressWarnings(“deprecation”) |
finally | finallyブロックの処理が正常に実行されない | @SuppressWarnings(“finally”) |
null | ヌルポインターへのアクセスが行われた | @SuppressWarnings(“null”) |
unchecked | 危険な可能性がある型キャストを行っている | @SuppressWarnings(“unchecked”) |
divzero | ゼロ除算を行っている | @SuppressWarnings(“divzero”) |
unused | 未使用のローカル変数がある | @SuppressWarnings(“unused”) |
ちなみに、警告名を個別に指定するのが面倒な場合は「@SuppressWarnings(“all”)」ですべての警告を抑制できますが、基本的には推奨しません。
@SuppressWarningsアノテーションは、あくまで「警告内容を理解したうえで、安全なプログラムを警告なしで書く」ためのものなので乱用はしないようにしましょう。またEclipseでは、不要な@SuppressWarningsアノテーションを書いた場合は、警告が出てしまいます。
「@SafeVarargs」は、「可変長引数のデータ型の安全性を保障する」ためのアノテーションです。可変長引数とは、メソッドが任意の数(0個以上)の引数を取ることができる機能。「呼び出し元がどれくらいデータを引き渡すかわからない」場合でも、柔軟なプログラミングができるので便利です。
しかし可変長引数の実態は「配列」なので、可変長引数がジェネリクス付きの場合は、メソッド内で安全な操作が行われてしまうことがあります。たとえば、可変長引数を「Object型配列」に変換して、危険な型キャストを行うなどです。
そのため、可変長引数がジェネリクス付きの場合は、その危険性を示すために「潜在的なヒープ汚染」警告が表示されます。しかし、確実に安全なソースコードを書いている場合は邪魔な警告なので、以下のサンプルコードのように「@SafeVarargs」で警告を抑制するのがおすすめです。
//サンプルプログラム
import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { // リスト形式に変換した文字列を、文字列として表示する for (String str : toList("A", "B", "C", "D", "E")) { System.out.println(str); } } // 可変長引数の警告を抑制するために「@SafeVarargsアノテーション」を付与する @SafeVarargs public static List toList(T... args) { // 可変長引数の文字列をリスト形式に変換する return Arrays.asList(args); } }
//実行結果
A
B
C
D
E
==============================
なお、@SafeVarargsアノテーションを使用しない場合、以下の画像のように警告が表示されます。
@SafeVarargsアノテーションを付与することで、警告が表示されなくなります。
以上のように、「@SafeVarargsアノテーション」を付けると余計な警告を抑制できます。ただし、@SafeVarargsアノテーションはメソッドが「final」もしくは「static」でなければ使えません。これは、オーバーライドされたメソッドでは、安全性を保障できないことが理由だと考えられます。
「@FunctionalInterface」は、インターフェースが「関数型インターフェース」であることを定義するためのアノテーションです。関数インターフェースは、ラムダ式やメソッド参照に使用できる便利な機能です。
ただし関数インターフェースは、「定義されている抽象メソッドがひとつだけ」で「実装されているメソッドがひとつもない」という条件を満たさなければ、関数インターフェースとして機能しません。そのため、関数インターフェースの定義にミスがあると、思わぬバグやエラーの原因になることがあります。
そこで便利なのが、@FunctionalInterfaceアノテーションです。対象となる関数インターフェースに付与することで、定義ミスがある場合にコンパイルエラーが出るようになります。以下のサンプルコードで詳細を確認しましょう。
//サンプルプログラム
// 関数型インターフェースであることを明示するために // 「@FunctionalInterfaceアノテーション」を付与する @FunctionalInterface interface TestInterface { public void method(); } class TestClass implements TestInterface { public void method() { System.out.println("関数型インターフェースのメソッド実行"); } } public class Main { public static void main(String[] args) { // TestClassのインスタンスを生成する TestClass test = new TestClass(); // TestClassのmethodを実行する test.method(); } }
//実行結果
関数型インターフェースのメソッド実行
以上のように、@FunctionalInterfaceアノテーションを付与することで、対象となるインターフェースが「関数インターフェース」であることを保障できます。なお、条件を満たさない関数インターフェースに@FunctionalInterfaceアノテーションを付与すると、以下のようにコンパイルエラーとなります。
// このクラスには抽象メソッドが複数あるため、
// 「関数インターフェース」の条件を満たしておらず、
// 「@FunctionalInterfaceアノテーション」を付与するとエラーになる
@FunctionalInterface
interface TestInterface {
public void methodA();
public void methodB();
public void methodC();
}
Javaの標準機能として利用できるアノテーションは、基本的には前述した「@Override」「@Deprecated」「@SuppressWarnings」「@SafeVarargs」「@FunctionalInterface」の5種類のみです。
一方で、Javaのアノテーションは自作することもできます。「自作アノテーション」を活用すれば、さらにわかりやすい注釈をソースコードに付与できるので便利です。ここからは、自作アノテーションの作成方法・使い方を以下5つのステップから解説します。
まずはアノテーション本体を定義します。自作アノテーションは、以下の構文で定義できますが、通常のクラスやインターフェース、メソッドとは異なるので注意してください。
@interface アノテーション名 { // 規定値を設定しない場合 型名 要素名(); // 規定値を設定する場合 型名 要素名() default 既定値; }
慣れるまでわかりにくいかもしれませんが、自作アノテーションは「@interface」の後ろに「アノテーション名」を記述すると定義できるでしょう。アノテーション内部では、アノテーションとして付与できる要素を指定し、必要に応じて規定値も指定できます。
なお、すべてのアノテーションは「java.lang.annotation.Annotation」を継承していますが、アノテーション定義に「extends」は不要です。以下のサンプルは、「作成者」「種類」「詳細説明」の情報を付与できるアノテーションになります。
// アノテーション本体を定義する @interface Annotation { // アノテーションを付与した要素の作成者 // 今回は「default」で規定値を「コードカキタイ」とする String author() default "コードカキタイ"; // アノテーションを付与する要素の種類 String type(); // アノテーションを付与する要素の詳細説明 String description(); }
次に「メタアノテーション」を追加します。メタアノテーションは「java.lang.annotation」パッケージで提供される機能で、自作アノテーションの「適用範囲」や「保持期限」など、アノテーションの性質を決めるためのものです。メタアノテーションには、大きく分けて以下4種類のものがあります。
メタアノテーション | 概要 | 指定方法(詳細後述) |
---|---|---|
@Documented | 付与したアノテーションを「JavaDoc」に含めるかどうか | ソースコードに「@Documented」と記載すれば、「JavaDoc」に含まれるようになる |
@Target | アノテーションをどの要素に付与できるか | 「java.lang.annotation.ElementType」の値から選択する |
@Retention | アノテーション情報がどの段階まで保存されるか | 「java.lang.annotation.RetentionPolicy」の値から選択する |
@Inherited | サブクラスにも同じアノテーションが継承されるか | ソースコードに「@Inherited」と記載すれば、サブクラスに継承されるようになる |
「@Documented」と「@Inherited」については、以下のようにソースコード中にそのまま記載すれば機能が有効化されます。なお、「@Documented」に関連する「JavaDoc」については、後ほど改めて解説します。
// 作成・付与した自作アノテーションを「JavaDoc」に含める @Documented // スーパークラスに付与したアノテーションを、サブクラスが継承するようにする @Inherited
「@Inherited」は、サブクラスにアノテーションを付与していないとき、自動的にスーパークラスに付与したアノテーションが適用される機能です。ただし、クラスに付与した場合のみ有効で、フィールドやメソッドのアノテーションは継承されません。
「@Target」と「@Retention」は、それぞれパッケージで規定された値から選択します。@Targetの代表的な値は以下のとおりです。
@Targetに指定できる値 | 概要 |
---|---|
ElementType.TYPE | クラス・インターフェース・アノテーション・enum型に対して、アノテーションを付与できる |
ElementType.FIELD | フィールドに対して、アノテーションを付与できる |
ElementType.CONSTRUCTOR | コンストラクタに対して、アノテーションを付与できる |
ElementType.METHOD | メソッドに対して、アノテーションを付与できる |
アノテーションはさまざまな要素に付与するため、基本的には上記4つのすべてを指定しておくと便利です。以下のように、「@Target({指定する値})」という構文で値を指定しましょう。
// 自作アノテーションの「Target」を定義する // クラス(TYPE)・フィールド(FIELD)・コンストラクタ(CONSTRUCTOR)・メソッド(METHOD) // 4種類いずれの要素に対して、アノテーションを付与できるか指定する @Target({ ElementType.TYPE, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD })
@Retentionに指定できる値は、以下3種類に限られています。
@Retentionに指定できる値 | 概要 |
---|---|
RetentionPolicy.SOURCE | アノテーション情報は、ソースコードの段階まで保持されるが、コンパイル時に破棄される |
RetentionPolicy.CLASS | アノテーション情報はコンパイルの段階まで保持されるが、実行時に、JVM(Java仮想マシン)に破棄される |
RetentionPolicy.RUNTIME | アノテーション情報はJVM(Java仮想マシン)に保持されるため、実行中にアノテーション情報を取得できる |
ほとんどの場合は、以下のように「RetentionPolicy.RUNTIME」を指定するので、定型文として覚えておくといいでしょう。
// 自作アノテーションの「Retention」を定義する // アノテーション情報をどの段階まで保持するか指定する // 「SOURCE」はソースコードの段階まで // 「CLASS」はコンパイルが行われるときまで // 「RUNTIME」は実行中もアノテーション情報を保持する @Retention(RetentionPolicy.RUNTIME)
メタアノテーションについて知っておくべき知識は以上のとおりです。ただし、メタアノテーションを指定する際は、値を定義しておくパッケージをimportする必要があります。その部分も含めて、メタアノテーションの定義方法を再確認しておきましょう。
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; // 作成・付与した自作アノテーションを「JavaDoc」に含める @Documented // 自作アノテーションの「Target」を定義する // クラス(TYPE)・フィールド(FIELD)・コンストラクタ(CONSTRUCTOR)・メソッド(METHOD) // 4種類いずれの要素に対して、アノテーションを付与できるか指定する @Target({ ElementType.TYPE, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD }) // 自作アノテーションの「Retention」を定義する // アノテーション情報をどの段階まで保持するか指定する // 「SOURCE」はソースコードの段階まで // 「CLASS」はコンパイルが行われるときまで // 「RUNTIME」は実行中もアノテーション情報を保持する @Retention(RetentionPolicy.RUNTIME) // スーパークラスに付与したアノテーションを、サブクラスが継承するようにする @Inherited
先ほどの手順で、自作アノテーションの定義自体は完了です。あとは以下のサンプルコードのように、実際にクラスやフィールド、メソッドなどにアノテーションを付与しましょう。
// クラスにアノテーションを付与する @Annotation(type = "クラス", description = "テスト用クラス") class Test { // フィールドにアノテーションを付与する @Annotation(author = "サンプルコード担当者", type = "フィールド", description = "テスト用フィールド") private int i = 0; // コンストラクタにアノテーションを付与する @Annotation(type = "コンストラクタ", description = "テスト用クラスのコンストラクタ") public Test() { System.out.println("Testクラスのコンストラクタ"); } // メソッドにアノテーションを付与する @Annotation(author = "サンプルコード担当者", type = "メソッド", description = "テスト用メソッド") public void method() { System.out.println("Testクラスで自作アノテーションを使用!"); } }
上記のサンプルコードでは、クラス・フィールド・コンストラクタ・メソッドにアノテーションを付与しています。ただし、「@Target」で値を正しく設定していない場合は、一部の要素にしかアノテーションを付与できないので要注意。
アノテーションの付与方法がわかりづらいかもしれませんが、要はメソッドに引数を引き渡すときのように、「@アノテーション名(各要素に値を代入)」という形式で記載すればOKです。デフォルト値を設定している場合を除き、すべての要素を記載する必要があります。
付与したアノテーション情報は、「java.lang.reflectパッケージ」の「リフレクション機能」を活用することで、プログラム実行中に取得できます。ただし「@Retention」に「RetentionPolicy.RUNTIME」を指定していなければ、この機能は使えないので要注意。アノテーション情報の取得方法は、以下のサンプルコードのとおりです。
public class Main { public static void main(String args[]) throws Exception { // アノテーションを付与したクラスのインスタンスを生成する Test test = new Test(); // テストクラスのメソッドを実行する test.method(); // クラス情報を取得する Class<?> classInfo = test.getClass(); // クラスに付与したアノテーションを取得する Annotation classAnnotation = classInfo.getAnnotation(Annotation.class); // フィールドに付与したアノテーションを取得する Field fieldInfo = classInfo.getDeclaredField("i"); Annotation fieldAnnotation = fieldInfo.getAnnotation(Annotation.class); // コンストラクタに付与したアノテーションを取得する Constructor<?> constructorInfo = classInfo.getConstructor(); Annotation constructorAnnotation = constructorInfo.getAnnotation(Annotation.class); // メソッドに付与したアノテーションを取得する Method methodInfo = classInfo.getMethod("method"); Annotation methodAnnotation = methodInfo.getAnnotation(Annotation.class); } }
複雑なプログラムになりましたが、重要なポイントはまず「Class<?>オブジェクト」に、アノテーションを付与したクラスの情報を取得することです。そのうえで、「getAnnotationメソッド」でアノテーションの種類を指定すると、「Annotationオブジェクト」にアノテーション情報が格納されます。
アノテーション情報の取得方法は、どのプログラムでも基本的には同じなので、「定型文」として覚えておくといいでしょう。なお、取得したアノテーション情報の扱い方については後述します。
これまでご紹介したステップを踏まえて、アノテーション情報の定義・付与・取得すべてを行うサンプルプログラムをご紹介します。
//サンプルプログラム
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; // 作成・付与した自作アノテーションを「JavaDoc」に含める @Documented // 自作アノテーションの「Target」を定義する // クラス(TYPE)・フィールド(FIELD)・コンストラクタ(CONSTRUCTOR)・メソッド(METHOD) // 4種類いずれの要素に対して、アノテーションを付与できるか指定する @Target({ ElementType.TYPE, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD }) // 自作アノテーションの「Retention」を定義する // アノテーション情報をどの段階まで保持するか指定する // 「SOURCE」はソースコードの段階まで // 「CLASS」はコンパイルが行われるときまで // 「RUNTIME」は実行中もアノテーション情報を保持する @Retention(RetentionPolicy.RUNTIME) // スーパークラスに付与したアノテーションを、サブクラスが継承するようにする @Inherited // アノテーション本体を定義する @interface Annotation { // アノテーションを付与した要素の作成者 // 今回は「default」で規定値を「コードカキタイ」とする String author() default "コードカキタイ"; // アノテーションを付与する要素の種類 String type(); // アノテーションを付与する要素の詳細説明 String description(); } // クラスにアノテーションを付与する @Annotation(type = "クラス", description = "テスト用クラス") class Test { // フィールドにアノテーションを付与する @Annotation(author = "サンプルコード担当者", type = "フィールド", description = "テスト用フィールド") private int i = 0; // コンストラクタにアノテーションを付与する @Annotation(type = "コンストラクタ", description = "テスト用クラスのコンストラクタ") public Test() { System.out.println("Testクラスのコンストラクタ"); } // メソッドにアノテーションを付与する @Annotation(author = "サンプルコード担当者", type = "メソッド", description = "テスト用メソッド") public void method() { System.out.println("Testクラスで自作アノテーションを使用!"); } } public class Main { public static void main(String args[]) throws Exception { // アノテーションを付与したクラスのインスタンスを生成する Test test = new Test(); // テストクラスのメソッドを実行する test.method(); // クラス情報を取得する Class<?> classInfo = test.getClass(); // クラスに付与したアノテーションを取得する Annotation classAnnotation = classInfo.getAnnotation(Annotation.class); // フィールドに付与したアノテーションを取得する Field fieldInfo = classInfo.getDeclaredField("i"); Annotation fieldAnnotation = fieldInfo.getAnnotation(Annotation.class); // コンストラクタに付与したアノテーションを取得する Constructor<?> constructorInfo = classInfo.getConstructor(); Annotation constructorAnnotation = constructorInfo.getAnnotation(Annotation.class); // メソッドに付与したアノテーションを取得する Method methodInfo = classInfo.getMethod("method"); Annotation methodAnnotation = methodInfo.getAnnotation(Annotation.class); // 改行する System.out.println(""); // クラスのアノテーションを表示する System.out.println("クラスのアノテーション"); System.out.println("作成者:" + classAnnotation.author()); System.out.println("種類:" + classAnnotation.type()); System.out.println("詳細説明:" + classAnnotation.description()); // 改行する System.out.println(""); // フィールドのアノテーションを表示する System.out.println("フィールドのアノテーション"); System.out.println("作成者:" + fieldAnnotation.author()); System.out.println("種類:" + fieldAnnotation.type()); System.out.println("詳細説明:" + fieldAnnotation.description()); // 改行する System.out.println(""); // コンストラクタのアノテーションを表示する System.out.println("コンストラクタのアノテーション"); System.out.println("作成者:" + constructorAnnotation.author()); System.out.println("種類:" + constructorAnnotation.type()); System.out.println("詳細説明:" + constructorAnnotation.description()); // 改行する System.out.println(""); // メソッドのアノテーションを表示する System.out.println("メソッドのアノテーション"); System.out.println("作成者:" + methodAnnotation.author()); System.out.println("種類:" + methodAnnotation.type()); System.out.println("詳細説明:" + methodAnnotation.description()); } }
//実行結果
Testクラスのコンストラクタ Testクラスで自作アノテーションを使用! クラスのアノテーション 作成者:コードカキタイ 種類:クラス 詳細説明:テスト用クラス フィールドのアノテーション 作成者:サンプルコード担当者 種類:フィールド 詳細説明:テスト用フィールド コンストラクタのアノテーション 作成者:コードカキタイ 種類:コンストラクタ 詳細説明:テスト用クラスのコンストラクタ メソッドのアノテーション 作成者:サンプルコード担当者 種類:メソッド 詳細説明:テスト用メソッド
注目したいポイントは、mainメソッドでアノテーション情報を取得している部分です。まずは「Class<?> classInfo = test.getClass();」でクラス情報を取得。「<?>」の部分は「ワイルドカード」と呼ばれ、getClassメソッドの戻り値を受けるために必要です。
そのうえで、自作した「Annotation」クラスの変数を宣言。getAnnotationメソッドの引数で自作アノテーションクラスを指定し、クラス・フィールド・コンストラクタ・メソッドそれぞれに付与したアノテーション情報を取得します。
あとはprintlnメソッドで、自作アノテーションクラスの各要素を取り出せば、すべての情報を表示できます。複雑なプログラムではありますが、ほとんどの部分は「定型文」として使いまわせるので便利です。
これまでご紹介した方法で、Javaのソースコードにアノテーションを付与しておくと、「JavaDoc」をわかりやすく生成できます。そもそも「JavaDoc」とは、簡単に言うとJavaのソースコードの説明書です。まるでホームページのような見た目でわかりやすく、ソースコードから自動的に生成することができます。
ソースコードの構造や内容、コメントやアノテーション情報などが表示されるので、ぜひ活用したい機能です。ただし、メタアノテーションで「@Documented」を有効化しておかないと、JavaDocにアノテーション情報が掲載されないので要注意。JavaDocは、Eclipseを使用している場合は以下の手順で簡単に作成できます。
IDE上部のメニューから、「プロジェクト」→「JavaDocを生成」をクリックします。
JavaDoc生成のオプション画面が表示されます。基本的にはデフォルト設定でOKですが、「次の可視性を持つメンバーのJavaDocを作成」は、「Private」にしておくとすべての情報が出力されるのでおすすめ。「完了」をクリックすると、すぐにJavaDocが作成されます。
なお、多数の警告が表示されるかもしれませんが、ほとんどは「コメントなし」が原因なので気にしなくて構いません。JavaDocを作成したら、以下の手順でJavaDocを表示してみましょう。
左側の「パッケージエクスプローラー」で現在のファイル名を選択し、「ナビゲート」→「添付されたJavaDocを開く」をクリックすると、先ほど生成されたJavaDocが開きます。
このように、WebブラウザでホームページのようにJavaDocを閲覧できます。上部のタブからクラスを選択すると、先ほど作成した自作アノテーションクラスのドキュメントもチェックできます。
なおJavaDocでは、アノテーションを日本語で記述すると、Unicodeの16進数で表示されてしまいます。基本的にはこれを解決する方法はないので、気になる場合はアノテーションをすべて英語で記載しましょう。
Javaのアノテーションは、ソースコードの誤入力や抜け漏れを防ぎ、正確なプログラムを作成するための機能。好ましくないコードを書いたときに、コンパイラがエラーや警告を出すようにできるので便利です。
複雑な手順が必要ですが、自作アノテーションも作成すれば、標準機能では利用できないアノテーションを付与できます。クラスやメソッドに詳しいコメントを記載できますし、JavaDocに含めることもできるので、ぜひ活用してみましょう。
2024.06.17
子供におすすめのプログラミングスクール10選!学習メリットや教室選びのコツも紹介
#プログラミングスクール
2022.01.06
【完全版】大学生におすすめのプログラミングスクール13選!選ぶコツも詳しく解説
#プログラミングスクール
2024.01.26
【未経験でも転職可】30代におすすめプログラミングスクール8選!
#プログラミングスクール
2024.01.26
初心者必見!独学のJava学習方法とおすすめ本、アプリを詳しく解説
#JAVA
2024.01.26
忙しい社会人におすすめプログラミングスクール15選!失敗しない選び方も詳しく解説
#プログラミングスクール
2022.01.06
【無料あり】大阪のおすすめプログラミングスクール14選!スクール選びのコツも紹介
#プログラミングスクール
2024.01.26
【目的別】東京のおすすめプログラミングスクール20選!スクール選びのコツも徹底解説
#プログラミングスクール
2024.01.26
【無料あり】福岡のおすすめプログラミングスクール13選!選び方も詳しく解説
#プログラミングスクール
2024.01.26
【徹底比較】名古屋のおすすめプログラミングスクール13選!選び方も詳しく解説
#プログラミングスクール
2024.01.26
【徹底比較】おすすめのプログラミングスクール18選!失敗しない選び方も徹底解説
#プログラミングスクール