アノテーション
- アノテーションとは
- オーバーライド(@Override)
- 非推奨(@Deprecated)
- 警告抑制(@SuppressWarnings)
- 安全可変引数(@SafeVarargs)
- 関数型インタフェース(@FunctionalInterface)
- カスタムアノテーション(@interface)
アノテーションとは
Java 5 から導入された機能で、クラス、インタフェース、メソッドなどの冒頭に記述することでプログラミング上のミスを低減したり付加機能を実装したりすることができます。
オーバーライド(@Override)
親クラスのメソッドをオーバーライドするメソッドに指定します。下記の例は clac() メソッドをオーバーライドしたつもりが型誤りのためにオーバーライドできていないケースですが、@Override をつけることでオーバーライドできていない時に method does not override or implement a method from a supertype エラーを発生させることができます。
class ClassA {
long calc(long x, long y) { return x + y; }
}
class ClassB extends ClassA {
@Override
int calc(int x, int y) { return x * y; }
}
非推奨(@Deprecated)
使用するクラスやメソッドなどが非推奨であることを示します。非推奨のクラスやメソッドを使用しようとした際、コンパイル時に警告が表示されます。
class ClassA {
@Deprecated
void hello() {
System.out.println("Hello!");
}
}
Java 9 からは since と forRemoval を指定できるようになりました。since はどのバージョンから非推奨になったか、forRemoval は将来削除される予定か否かを指定します。
@Deprecated(since="1.3") @Deprecated(forRemoval=true) @Deprecated(since="1.3", forRemoval=true)
警告抑制(@SuppressWarnings)
コンパイル時の警告を抑制します。無視したい警告を抑制することで、無視してはならない警告に気づきやすくなります。type には警告の種別を指定します。
@SuppressWarnings(type)
deprecation は非推奨の機能を使用する際の警告を抑制します。
class Test {
@Deprecated
static void hello() { System.out.println("Hello!"); }
}
class Main {
@SuppressWarnings("deprecation")
public static void main(String[] args) {
Test.hello(); // 非推奨機能
}
}
removal は削除予定の機能を使用する際の警告を無視します。
class Test {
@Deprecated(forRemoval=true)
static void hello() { System.out.println("Hello!"); }
}
class Main {
@SuppressWarnings("removal")
public static void main(String[] args) {
Test.hello(); // 削除予定機能
}
}
preview はプレビュー機能を使用する際の警告を抑制します。例えば Java 21 ではプレビュー版である ScoppedValue を使用する際の警告を抑制するには次の様にします。Java 21 で javac コマンドに --enable-preview --release 21 オプションを、java コマンドに --enable-preview オプションを指定して実行してください。
@SuppressWarnings("preview")
class Test {
final ScopedValue<String> STR = ScopedValue.newInstance(); // プレビュー機能
}
unchecked は型が保証されていない場合の警告を抑制します。
import java.util.*;
class Main {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("AAA");
}
}
安全可変引数(@SafeVarargs)
Java 7 で導入されました。可変引数の処理が安全であることを示します。final か static をつける必要があります。
import java.util.*;
class Foo<T> {
@SafeVarargs
public final void m(T... args) {
System.out.println(Arrays.toString(args));
}
}
安全ではない可変引数の処理の例は下記などを参照してください。
関数型インタフェース(@FunctionalInterface)
インタフェースが 関数型インタフェース であることを明示します。
@FunctionalInterface
interface SampleInterface {
public void hello();
}
カスタムアノテーション(@interface)
@interface でアノテーションを自作することもできます。@Documented を指定すると javadoc ドキュメントに反映されることを意味します。@Target にはアノテーションを何に適用できるかを TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VALIABLE, ANNOTATION_TYPE, PACKAGE のリストで指定します。@Retention はアノテーションが保持されるレベルを SOURCE(ソースのみ), CLASS(クラスファイルに保持), RUNTIME(実行時にも保持) のいずれかで指定します。下記の例では、MyClass を継承し、@MyAnnotation をつけたメソッドは、インスタンス作成時に value1 と value2 の値を表示して、実行します。
import java.lang.annotation.*;
import java.lang.reflect.Method;
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String value1() default "";
int value2() default 0;
}
class MyClass {
MyClass() {
try {
Method[] methods = this.getClass().getMethods();
for (Method method : methods) {
MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
if (annotation != null) {
System.out.println("method: " + method);
System.out.println("value1: " + annotation.value1());
System.out.println("value2: " + annotation.value2());
method.invoke(this);
}
}
} catch (Exception e) {
System.out.println(e);
}
}
}
class Foo extends MyClass {
@MyAnnotation(value1="ABC", value2=123)
public void methodA() {
System.out.println("methodA");
}
@MyAnnotation(value1="XYZ", value2=987)
public void methodB() {
System.out.println("methodB");
}
}
class Main {
public static void main(String[] args) {
Foo foo = new Foo();
}
}