Java では、インタフェースのメソッドをクラスが実装していないとコンパイルエラーになります。
でも、 実行時には未実装のメソッドを呼び出そうとしない限りはエラーになりません。
実験
最初にエラーにならないように実装して、あとからインタフェースにメソッドを追加します。
まず、X
というインタフェースを用意します。
public interface X {
void foo();
}
次に、これを実装した XImpl
というクラスを用意します。
public class XImpl implements X {
@Override
public void foo() {
System.out.println("foo");
}
}
最後に、これを実行する Main
クラスを用意します。
public class Main {
public static void main(String... args) {
System.out.println("main");
call(new XImpl());
}
private static void call(X x) {
x.foo();
}
}
これを、コンパイルして実行します。
$ javac X.java XImpl.java Main.java
$ java Main
main
foo
問題なく実行できます。
ここで X
インタフェースに bar
メソッドを追加してコンパイルします。
public interface X {
void foo();
void bar(); // 追加
}
$ javac X.java
このとき、XImpl
クラスには X
インタフェースの bar
メソッドが実装されていない状態です。
でも、実行してもエラーにはなりません。
$ java Main
main
foo
実装されていないメソッドを実行しようとすると?
今度は、Main
クラスを書き換えて、実装されていない bar
メソッドを呼び出してみます。
public class Main {
public static void main(String... args) {
System.out.println("main");
call(new XImpl());
}
private static void call(X x) {
x.bar(); // foo() から bar() に変更
}
}
これは、実行時に AbstractMethodError
が発生します。
(NoSuchMethodError
ではない)
$ javac Main.java
$ java Main
main
Exception in thread "main" java.lang.AbstractMethodError: Receiver class XImpl does not define or inherit an implementation of the resolved method 'abstract void bar()' of interface X.
at Main.call(Main.java:7)
at Main.main(Main.java:3)
なんで?
「インタフェースが更新された際に、その実装が使えなくなってしまうのを防ぐため」だそうです。