Подкласс, полученный из Serviceloader, генерирует AbstractMethodError
Я пытаюсь сделать приложение Java, которое может загружать плагины, реализующие абстрактный класс, и у меня есть AbstractMethodError с экземплярами, сгенерированными из ServiceLoader. Код немного тяжелый, поэтому я сделал упрощение ниже.
Во-первых, у меня есть абстрактный класс:
package stuff.TheAbstractClass;
public abstract class TheAbstractClass implements ClassInterface{
//Stuff happens
}
Который реализует следующий интерфейс:
package stuff.ClassInterface;
public interface ClassInterface {
public String getClassName();
}
У меня есть поставщик услуг NotAbstractClass
который расширяется TheAbstractClass
и так в папке meta-inf / services:
package anotherstuff.NotAbstractClass;
public final class NotAbstractClass extends TheAbstractClass implements ClassInterface{
private String name = "Silent Bob";
@Override
public String getClassName() { return name; }
}
Затем в основном приложении (которое на самом деле является плагином внутри другого приложения) я хочу найти все классы, которые расширяют TheAbstractClass
:
package stuff.TheApp;
import java.util.ServiceLoader;
public class TheApp {
private String name;
public final static TheApp INSTANCE = new TheApp();
private TheApp() {
ServiceLoader<TheAbstractClass> serviceLoader =
ServiceLoader.load(TheAbstractClass.class);
for (TheAbstractClass class: serviceLoader) {
name = class.getClassName;
}
}
Мое приложение находит NotAbstractClass
, Я знаю это, так как в цикле я могу сделать class.getName()
и это даст мне anotherstuff.NotAbstractClass
) но выдает ошибку:java.lang.AbstractMethodError: stuff.TheAbstractClass.getClassName()Ljava/lang/String;
Я в тупике. Любое предложение? Спасибо, Педро
2 ответа
Кажется, проблема была не в коде, а в IDE (IntelliJ). Я удалил все ранее упакованные фляги и сделал новые фляги, ничего не изменяя, и это волшебно работало... Так что это ошибка IDE, а не проблема языка! Спасибо @Joao и @hotzst за то, что нашли время почитать. Бест, Педро
Согласно API для AbstractMethodError вы получите это:
Брошенный, когда приложение пытается вызвать абстрактный метод. Обычно эта ошибка отлавливается компилятором; эта ошибка может возникнуть только во время выполнения, если определение некоторого класса несовместимо изменилось с момента последней компиляции выполняемого в данный момент метода.
Просто глядя на ваш код и ваш комментарий, я вижу, что это могло произойти только во время выполнения.
Если это так, то:
какой-то класс несовместимо изменился, так как текущий выполняемый метод был скомпилирован последним
Я проверил вашу логику после некоторых настроек в Java-совместимой форме, и у меня не было проблем. Единственное, что, кажется, происходит, - это изменение в любом из подклассов TheAbstractClass
,
Еще я хотел объявить зависимости, используя файлы зависимостей в: resources/META-INF/services:
файл: <полный пакет>.TheAbstractClass
content: <полный пакет>.NotAbstractClass
После этого у меня не было проблем.