Java Gold コンパイルエラーと実行時エラーについての疑問
解決したいこと
Java Goldの黒本を解いていた時に疑問に思っていたことを解決したいです。
該当する問題
- (Java Gold黒本第13章8問目参照)
次のプログラムをコンパイル、実行した時の結果として、正しいものを選びなさい
public interface Test{
public default void execute(String str){
System.out.println("A");
}
}
public abstract class AbstractTest{
private void execute(String str){
System.out.println("B");
}
}
public class Sample extends AbstractTest implements Test{
public static void main(String[] args){
new Sample().execute("hello");
}
}
A.「A」と表示される
B.「B」と表示される
C.コンパイルエラーが発生する
D.実行時に例外が発生する
正解:D
クラスに定義しているメソッドが優先されるというルールはコンパイル時に適用されるため、コンパイラはインターフェースに定義されているpublicなexecuteメソッドを実行するものと解釈し、コンパイルは成功します。しかし、実行時には前述のルールが適用されるため、不正なアクセスをしたことを示す例外IkkegalAccessErrorがスローされます。
2.(Java Gold黒本第1章13問目参照)
次のプログラムをコンパイル、実行した時の結果として正しいものを選びなさい
public interface A{
public default void test(){
System.out.println("A");
}
}
public abstract class B{
protected void test(){
System.out.println("B");
}
}
public class Sample extends B implements A{
public static void main(String[] args){
new Sample().test();
}
}
A.「A」と表示される
B.「B」と表示される
C.コンパイルエラーが発生する
D.実行時に例外が発生する
正解:C
Sampleクラスが実現しているAインターフェースと継承しているBクラスが、同じシグニチャのメソッドを持っています。コンパイラは、SampleクラスはBクラスを引き継いだ上でAインターフェースを実現していると解釈されます。
Bクラスから引き継いだtestメソッドが、Aインターフェースに定義されているtestメソッドと互換性がないと判断されるため、コンパイラエラーが発生します。
分からないこと
二つのコードを見比べるととても似ていますが、片方はコンパイルエラー、片方は例外をスローと違う結果になります。
二つのコードの相違点といえば、abstractクラスのメソッドがprivateかabstractかどうかや、メソッドの引数がないかどうかくらいです。
今自分の中の仮説では、privateなメソッドはコンパイラが検知できないため、コンパイル自体は成功するが実行時に例外がスローされる。と言うものです。
テキストの解説には特にそのような説明はありませんでしたので、確実ではありません。
なぜそうなっているのか、原理原則を踏まえてご教授願います。