The King's Museum

ソフトウェアエンジニアのブログ。

【Effective Java】項目37:型を定義するためにマーカーインタフェースを使用する

マーカーインタフェース

マーカーインタフェースはメソッド宣言を一つももたないインタフェースです。 そのインタフェースを実装しているクラスが何か特別な性質を持っていることを示すために宣言します。

たとえば Serializable インタフェースはマーカーインタフェースです。 Serializable はメソッドを一つも持ちませんが、ObjectOutputStream に利用できるという特性を持っていることを示します。

ObjectOutputStream.write(Object o) に Serializable を実装していないインスタンスを渡すと例外が発生します。 本来、write の宣言は Object ではなく Serializable を引数にとるべきでした。 そうすれば、実行時の例外ではなくコンパイル時のエラーとして間違いを見つけることが出来ます。

マーカーアノテーション

一方、マーカーアノテーションはその名の通り、何らかの特性を示すためのアノテーションです。

アノテーション自体がメタデータを示すものなので、大抵、アノテーションはマーカーアノテーションとしての役割を果たします。

どちらを使えばいいか

一般的に、マーカーインタフェースが利用できるならばマーカーアノテーションよりもマーカーインタフェースを使うべきです。

マーカーインタフェースは型を定義できるため、コンパイル時にその特性をチェックすることができます。 マーカーアノテーションは一般的に実行時までその特性をチェックすることはできません。 (コンパイラが対応している @Override アノテーションなどは特別です)

特に、このマーカーを付与したクラスをメソッドの引数に使いたい場合は、マーカーインタフェースを用いるべきです。

ただし、マーカーインタフェースはクラス以外をマークすることが出来ません。 メソッドやフィールドをマークしたい場合はマークアのテーションを使う必要があります。

マーカーアノテーションにデフォルト値をもたせて置けば、あとから値を追加することができます。 しかし、マーカーインタフェースにあとからメソッドを追加することは一般的にはできません。 コンパイル互換性を破壊するからです。

まとめ

まとめると、一般的にはマーカーインタフェースが使える場合はそちらを使うべきです。 しかし、メソッドやフィールドをマークしたい場合など、マーカーインタフェースが利用できない、または適さない場合はマーカーアノテーションを使うべきです。

(c) The King's Museum