倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

@Override アノテーション

Effective Java 第2版 (The Java Series)』を読むまで知らなかったのですが、Java SE 5 から Java SE 6 に移行する際に @Override アノテーション*1の使用方法が変更になっていたそうで。

一言で言えば、「インターフェースに宣言されているメソッドをオーバーライドする際にも @Override アノテーションを使える」ように拡張されました。 確かに Java SE 5 の頃に何故こういう風に使えないんだ!と思ったことがありましたが、拙者だけではなかったのですね。

以下で、Java SE 5 と Java SE 6 の間の @Override アノテーションの使い方の違いを、サンプル・コードを用いて見ていきましょう。

分類表


拡張する型 (extends) と拡張される型 (super) で、有り得る組合せは以下の表の通り:

extends \ super インターフェース 抽象クラス 具象クラス
インターフェース interface I extends I - -
抽象クラス abstract class AC
 implements I
abstract class AC
 extends AC
abstract class AC
 extends CC
具象クラス class CC implements I class CC extends AC class CC extends CC

ここで

  • I:インターフェース
  • AC:抽象クラス
  • CC:具象クラス

です。 Java SE 6 から @Override アノテーションを付加することが可能になったのは、拡張される型 (super) がインターフェースの場合です(黄色い部分)。 それ以外のものは従来から可能です。

インターフェースを拡張する


Java SE 6 で @Override アノテーションを付加できるようになったのは「インターフェースを拡張する」場合です。

インターフェース extends インターフェース

interface SuperInterface{
    void method();
}

interface Interface extends SuperInterface{
    /** Java SE 6 から可能に。 */
    @Override void method();
}

抽象クラス implements インターフェース

interface Interface{
    void method1();
    void method2();
}

abstract class AbstractClass implements Interface{
    /** Java SE 6 から可能に。 */
    @Override public abstract void method1();

    /** Java SE 6 から可能に。 */
    @Override public void method2(){}
}

「抽象メソッドでオーバーライド」する場合と「具象メソッドでオーバーライド」する場合がありますが、どちらも可能になりました。

具象クラス implements インターフェース

interface Interface{
    void method();
}

class ConcreteClass implements Interface{
    /** Java SE 6 から可能に。 */
    @Override public void method(){}
}

抽象クラスを拡張する


これ以降(具象クラスを拡張する場合も)は、Java SE 5 と Java SE 6 との間に、@Override アノテーションの使用方法に違いはないので、別に読み飛ばしても構いません。

抽象クラス extends 抽象クラス

abstract class SuperAbstractClass{
    public abstract void abstractMethod1();
    public abstract void abstractMethod2();
    public void concreteMethod1(){}
    public void concreteMethod2(){}
}

abstract class AbstractClass extends SuperAbstractClass{
    /** もともと OK  */
    @Override public abstract void abstractMethod1();

    /** もともと OK */
    @Override public void abstractMethod2(){}

    /** もともと OK */
    @Override public abstract void concreteMethod1();

    /** もともと OK */
    @Override public void concreteMethod2(){}
}

オーバライドするメソッド・されるメソッドが抽象メソッドか具象メソッドかで、4パターンあります。

具象クラス extends 抽象クラス

abstract class SuperAbstractClass{
    public abstract void abstractMethod();
    public void concreteMethod(){}
}

class ConcreteClass extends SuperAbstractClass{
    /** もともと OK */
    @Override public void abstractMethod(){}

    /** もともと OK */
    @Override public void concreteMethod(){}
}

具象クラスを拡張する


ここも Java SE 5 と Java SE 6 との間で、@Override アノテーションの使用方法に違いはありません。 そもそも、具象クラスを拡張すること自体、あまり推奨されていません。

抽象クラス extends 具象クラス

class SuperConcreteClass{
    public void method1(){}
    public void method2(){}
}

abstract class AbstractClass extends SuperConcreteClass{
    /** もともと OK */
    @Override public abstract void method1();

    /** もともと OK */
    @Override public void method2(){}
}

具象クラス extends 具象クラス

class SuperConcreteClass{
    public void method(){}
}

class ConcreteClass extends SuperConcreteClass{
    /** もともと OK */
    @Override public void method(){}
}

Effective Java 第2版 (The Java Series)

Effective Java 第2版 (The Java Series)

*1:普通「@Override」もしくは「Override アノテーション」と書くのが正しいのでしょうが、ここでは「@Override アノテーション」と書きます。 特に深い意味はありませんが。