Эта проблема может возникнуть, если вы хотите вызвать реализацию default
метода, который не имеет default
реализации в interface
, который ваш класс явно implements
это.(Но имеет default
реализацию в базе (родитель, супер) interface
из этого interface
).
Пример: предположим, что эти определения:
class A implements DerivedInterface /*, ...*/ {
@Override public void methodFromBaseInterface() {
DerivedInterface.super.methodFromBaseInterface(); // Error:
// NoSuchMethodError: No static method methodFromBaseInterface
}
// ...
}
interface DerivedInterface extends BaseInterface {
// ...
// `methodFromBaseInterface` hasn't overriden here.
}
interface BaseInterface {
default void methodFromBaseInterface() { /* ...*/ }
// ...
}
Затем выполните:
A a = new A();
a.methodFromBaseInterface(); // This cause above error!
И вы получите ошибку в указанной точке!
(Заметка на полях: вам может потребоваться определить хотя бы один метод в DerivedInterface
, чтобы избежать получения NoClassDefFoundError
во время выполнения!)
Это похоже наЖук! Мы использовали super
ключевое слово.Почему ожидался метод static
? !! Другой момент заключается в том, что в приведенном выше коде нет проблем, и вы можете без проблем запустить его в любой среде, совместимой с Java 8!
Я думаю, что проблема связана с неполной поддержкой API языка Java 8 на платформе Android :
Android Studio 3.0 и более поздних версийподдерживает все функции языка Java 7 и подмножество функций языка Java 8, которые зависят от версии платформы .
Специально см. API языка Java 8 и Совместимость minSdkVersion таблица на этой странице :
java.lang.FunctionalInterface
: уровень API 24 или выше.
Обходные пути, которые я нашел:
Если у вас есть доступ к определению DerivedInterface
, просто переопределите methodFromBaseInterface
и явно делегируйте его интерфейсу super
:
interface DerivedInterface extends BaseInterface {
@Override default void methodFromBaseInterface() {
BaseInterface.super.methodFromBaseInterface();
}
// ...
}
Определите середину class
, которая реализует BaseInterface
и выведите из нее A
.Затем запустите methodFromBaseInterface
косвенно бросьте середину class
:
class MiddleClass /*extends B*/ implements BaseInterface {}
class A extends MiddleClass implements DerivedInterface {
@Override public void methodFromBaseInterface() {
super.methodFromBaseInterface(); // Indirectly from `MiddleClass`
}
// ...
}
Примечание: раскомментируйте /*extends B*/
, если у вашего A
класса ранее был super
с именем B
.