@Override が通らないときの確認手順
名前・引数・可視性の3点が一致条件です。オーバーロードとの違いを実例で確認します。
エラーメッセージの読み方
Main.java:5: error: method does not override or implement a method from a supertype
Main.java- ファイル名
5- 行番号 — javacが異常に気づいた位置。原因の行とは限りません
error- 種別 — コンパイルエラー。実行まで到達しません
method does not override or implement a method from a supertype- 内容 — javacが期待していたもの、または見つけられなかったもの
このエラーが出る典型パターン
パターン1
1 class Animal { 2 void speak() { System.out.println("..."); } 3 } 4 public class Main extends Animal { 5 @Override 6 void Speak() { System.out.println("Hello"); } ^ 7 public static void main(String[] args) { 8 new Main().speak(); 9 } 10 }
Main.java:5: error: method does not override or implement a method from a supertype
@Overrideは名前と引数が完全一致しないと通りません。この注釈がタイプミスを検出してくれます。
直し方: Speak を speak にします。
広告
広告スロット(未設定)
パターン2
1 class Base { 2 void run(String s) { System.out.println("base"); } 3 } 4 public class Main extends Base { 5 @Override 6 void run(Object s) { System.out.println("main"); } ^ 7 public static void main(String[] args) { 8 new Main().run("x"); 9 } 10 }
Main.java:5: error: method does not override or implement a method from a supertype
引数の型が違うとオーバーライドではなくオーバーロードになります。別のメソッドとして扱われます。
直し方: Object を String にします。
パターン3
1 class Base { 2 protected void run() {} 3 } 4 public class Main extends Base { 5 @Override 6 private void run() {} ^ 7 public static void main(String[] args) { 8 new Main().run(); 9 } 10 }
Main.java:6: error: run() in Main cannot override run() in Base
attempting to assign weaker access privileges; was protected
オーバーライドで可視性を狭めることはできません。同じか、より広くする必要があります。
直し方: private を public にします。
パターン4
1 class Base { 2 void handle(int n) { System.out.println("base"); } 3 } 4 public class Main extends Base { 5 @Override 6 void handle(Integer n) { System.out.println("main"); } ^ 7 public static void main(String[] args) { 8 new Main().handle(5); 9 } 10 }
Main.java:5: error: method does not override or implement a method from a supertype
intとIntegerは別の型です。オートボクシングで自動変換されても、オーバーライドの型一致には使えません。
直し方: Integer を int にします。
パターン5
1 class Base { 2 Object get() { return "x"; } 3 } 4 public class Main extends Base { 5 @Override 6 int get() { return 1; } ^ 7 public static void main(String[] args) { 8 System.out.println(new Main().get()); 9 } 10 }
Main.java:6: error: get() in Main cannot override get() in Base
戻り値の型はObjectのサブタイプなら変更できます(共変戻り値)。ただしintのようなプリミティブ型はObjectのサブタイプではないため使えません。
直し方: int を Integer にします。
よくある誤解
@Overrideは必須ではありませんが、付けないとタイプミスが黙って通ります。オーバーライドのつもりが新しいメソッドになります。
実務での勘所
戻り値の型は、オーバーライドする側とされる側で完全に一致させる必要はありません。Java 5以降は共変戻り値型(covariant return type)が認められており、親クラスがAnimalを返すメソッドを、子クラスの実装ではより具体的なDog(Animalのサブクラス)を返すようにオーバーライドできます。@Overrideが通らないとき、名前や引数は合っているのに戻り値の型で失敗している場合は、戻り値がサブクラスの関係になっているかを確認してください。