Рубрики
Без рубрики

AbstractMethodError в Java

Взгляните поближе на абстрактную ошибку Java и поймите, что это такое и когда это может произойти

Автор оригинала: Kai Yuan.

1. Обзор

Иногда мы можем столкнуться с Abstractmethod во время выполнения в нашем приложении. Если мы не знаем эту ошибку хорошо, может потребоваться некоторое время, чтобы определить причину проблемы.

В этом уроке мы подробнее рассмотрим Abstractmetoderror . Мы поймем, что такое Abstractmetoderror и когда это может произойти.

2. Введение в Abstractmetoderror

Абстрактметодеррор выбрасывается, когда приложение пытается вызвать нереализованный абстрактный метод.

Мы знаем, что если есть нереализованные абстрактные методы, компилятор сначала пожалуется. Таким образом, приложение вообще не будет построено.

Мы можем спросить, как мы можем получить эту ошибку во время выполнения?

Во-первых, давайте посмотрим, где Abstractmethod Error вписывается в иерархию исключений Java:

java.lang.Object
|_java.lang.Throwable
  |_java.lang.Error
    |_java.lang.LinkageError
      |_java.lang.IncompatibleClassChangeError
        |_java.lang.AbstractMethodError

Как видно из приведенной выше иерархии, эта ошибка является подклассом IncompatibleClassChangeError . Как следует из названия родительского класса, Abstractmethod обычно возникает, когда существуют несовместимости между скомпилированными классами или файлами JAR.

Далее давайте разберемся, как может произойти эта ошибка.

3. Как Может Произойти Эта Ошибка

Когда мы создаем приложение, обычно мы импортируем некоторые библиотеки, чтобы облегчить нашу работу.

Допустим, в нашем приложении мы включаем библиотеку baeldung-queue . Библиотека baeldung-queue -это библиотека спецификаций высокого уровня, которая содержит только один интерфейс:

public interface BaeldungQueue {
    void enqueue(Object o);
    Object dequeue();
}

Кроме того, чтобы использовать интерфейс BaeldungQueue , мы импортируем библиотеку реализации BaeldungQueue : good-queue . Библиотека good-queue также имеет только один класс:

public class GoodQueue implements BaeldungQueue {
    @Override
    public void enqueue(Object o) {
       //implementation 
    }

    @Override
    public Object dequeue() {
        //implementation 
    }
}

Теперь, если оба good-queue и baeldung-queue находятся в пути к классу, мы можем создать экземпляр BaeldungQueue в нашем приложении:

public class Application {
    BaeldungQueue queue = new GoodQueue();

    public void someMethod(Object element) {
        queue.enqueue(element);
        // ...
        queue.dequeue();
        // ...
    }
}

Пока все идет хорошо.

Когда-нибудь мы узнаем, что baeldung-queue выпущенная версия 2.0 и что он поставляется с новым методом:

public interface BaeldungQueue {
    void enqueue(Object o);
    Object dequeue();

    int size();
}

Мы хотим использовать новый метод size() в нашем приложении. Поэтому мы обновляем библиотеку baeldung-queue с 1.0 чтобы 2.0 . Однако мы забываем проверить, есть ли новая версия библиотеки good-queue , которая реализует изменения интерфейса BaeldungQueue .

Таким образом, у нас есть good-queue 1.0 и baeldung-queue 2.0 в пути к классу.

Далее мы начинаем использовать новый метод в нашем приложении:

public class Application {
    BaeldungQueue queue = new GoodQueue();

    public void someMethod(Object element) {
        // ...
        int size = queue.size(); //<-- AbstractMethodError will be thrown
        // ...
    }
}

Наш код будет скомпилирован без каких-либо проблем.

Однако, когда строка queue.size() выполняется во время выполнения, будет вызвана ошибка abstractmethod . Это связано с тем, что good-очередь 1.0 библиотека не реализует метод size() в интерфейсе BaeldungQueue .

4. Пример Из Реального Мира

С помощью простого сценария BaeldungQueue и Good Queue мы можем получить представление о том, когда приложение может выдать AbstractMethodError.

В этом разделе мы рассмотрим практический пример AbstractMethodError .

java.sql.Connection является важным интерфейсом в API JDBC. Начиная с версии 1.7, в интерфейс Connection было добавлено несколько новых методов, таких как GetSchema() .

База данных H2 -это довольно быстрая база данных SQL с открытым исходным кодом. Начиная с версии 1.4.192 , он добавил поддержку метода java.sql.Connection.GetSchema () . Однако в предыдущих версиях база данных H2 еще не реализовала этот метод.

Затем мы вызовем метод java.sql.Connection.GetSchema() из приложения Java 8 на более старой версии базы данных H2 1.4.191 . Посмотрим, что будет дальше.

Давайте создадим класс модульного теста, чтобы проверить, вызовет ли метод Connection.GetSchema() метод Abstractmethod error :

class AbstractMethodErrorUnitTest {
    private static final String url = "jdbc:h2:mem:A-DATABASE;INIT=CREATE SCHEMA IF NOT EXISTS myschema";
    private static final String username = "sa";

    @Test
    void givenOldH2Database_whenCallgetSchemaMethod_thenThrowAbstractMethodError() throws SQLException {
        Connection conn = DriverManager.getConnection(url, username, "");
        assertNotNull(conn);
        Assertions.assertThrows(AbstractMethodError.class, () -> conn.getSchema());
    }
}

Если мы запустим тест, он пройдет, подтвердив, что вызов GetSchema() вызывает AbstractMethodError .

5. Заключение

Иногда мы можем видеть Abstractmethod Error во время выполнения. В этой статье мы обсудили, когда возникает ошибка, на примерах.

Когда мы обновляем одну библиотеку нашего приложения, всегда рекомендуется проверить, используют ли другие зависимости эту библиотеку, и рассмотреть возможность обновления связанных зависимостей.

С другой стороны, как только мы столкнемся с AbstractMethodError , с хорошим пониманием этой ошибки, мы можем быстро решить проблему.

Как всегда, полный исходный код статьи доступен на GitHub .