Вызов метода по умолчанию в интерфейсе при конфликте с приватным методом

Рассмотрим ниже иерархию классов.

class ClassA {
    private void hello() {
        System.out.println("Hello from A");
    }
}

interface Myinterface {
    default void hello() {
        System.out.println("Hello from Interface");
    }
}

class ClassB extends ClassA implements Myinterface {

}

public class Test {
    public static void main(String[] args) {
        ClassB b = new ClassB();
        b.hello();
    }
}

Запуск программы даст следующую ошибку:

Exception in thread "main" java.lang.IllegalAccessError: tried to access method com.testing.ClassA.hello()V from class com.testing.Test
at com.testing.Test.main(Test.java:23)
  1. Это все потому, что я обозначил ClassA.hello как закрытый.
  2. Если я помечаю ClassA.hello как защищенный или удаляю модификатор видимости (т.е. Делая его по умолчанию), тогда он показывает ошибку компилятора как: The inherited method ClassA.hello() cannot hide the public abstract method in Myinterface

Однако, согласно вышеописанному исключению stacktrace, я получаю runtime IllegalAccessError.

Я не мог понять, почему это не обнаружено во время компиляции. Любые подсказки?

Ответы

Ответ 1

Обновление: Кажется, это действительно ошибка.

Объявление класса или суперкласса всегда имеет приоритет над методом по умолчанию!

метод default hello(...) из Myinterface позволяет писать без ошибок:

ClassB b = new ClassB();
b.hello();

До запуска, потому что во время выполнения hello(...) метод из ClassA принимает наивысший приоритет (но метод является приватным). Поэтому происходит IllegalAccessError.

Если вы удалите метод hello(...) по умолчанию из интерфейса, вы получите ту же ошибку незаконного доступа, но теперь во время компиляции.