Contents

Java中的AbstractMethoderror

1. 概述

有时,我们可能会在应用程序的运行时遇到*AbstractMethodError *  。如果我们不太了解此错误,则可能需要一段时间才能确定问题的原因。

在本教程中,我们将仔细研究AbstractMethodError。我们将了解AbstractMethodError是什么以及它何时发生。

2. AbstractMethodError简介

当应用程序尝试调用未实现的抽象方法时,将引发 AbstractMethodError

我们知道,如果有未实现的抽象方法,编译器会首先抱怨。因此,应用程序根本不会被构建。 我们可能会问我们如何在运行时得到这个错误?

首先,让我们看一下AbstractMethodError适合 Java 异常层次结构的位置:

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

如上面的层次结构所示,此错误是IncompatibleClassChangeError的子类。正如其父类的名称所暗示的,当编译的类或 JAR 文件之间存在不兼容时,通常会抛出AbstractMethodError

接下来,让我们了解这个错误是如何发生的。

3. 这个错误是如何发生的

当我们构建应用程序时,通常我们会导入一些库以使我们的工作更轻松。

假设,在我们的应用程序中,我们包含一个blogdemo-queue 库。blogdemo-queue 库是一个高级规范库,它只包含一个接口:

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

此外,为了使用BlogdemoQueue接口,我们导入了一个BlogdemoQueue实现库:good-queuegood-queue库 也只有一个类:

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

现在,如果good-queueblogdemo-queue 都在类路径中,我们可以在我们的应用程序中创建一个BlogdemoQueue实例:

public class Application {
    BlogdemoQueue queue = new GoodQueue();
    public void someMethod(Object element) {
        queue.enqueue(element);
        // ...
        queue.dequeue();
        // ...
    }
}

到目前为止,一切都很好。 有一天,我们了解到blogdemo-queue发布了2.0 版并且它附带了一种新方法:

public interface BlogdemoQueue {
    void enqueue(Object o);
    Object dequeue();
    int size();
}

我们想在我们的应用程序中使用新的size()方法。因此,我们将blogdemo-queue库从1.0升级到2.0。但是,我们忘记检查是否有实现BlogdemoQueue接口更改的good-queue库的新版本。

因此,我们在类路径中有good-queue 1.0blogdemo-queue 2.0  。

此外,我们开始在我们的应用程序中使用新方法:

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

我们的代码将毫无问题地编译。 但是,当 line  queue.size()在运行时执行时,会抛出AbstractMethodError。这是因为good-queue 1.0库没有在BlogdemoQueue接口中实现方法size()

4. 一个真实的例子

通过简单的BlogdemoQueueGoodQueue场景,我们可以知道应用程序何时可能会抛出AbstractMethodError

在本节中,我们将看到AbstractMethodError的一个实际示例。 java.sql.Connection 是 JDBC API 中的一个重要接口。从 1.7 版本开始, Connection接口中添加了几个新方法,例如getSchema()H2 数据库 是一个非常快速的开源 SQL 数据库。从版本1.4.192 开始,它增加了对java.sql.Connection.getSchema()*方法的支持。但是在之前的版本中,H2数据库还没有实现这个方法。

接下来,我们将从旧 H2 数据库1.4.191版本上的 Java 8 应用程序调用*java.sql.Connection.getSchema()*方法。让我们看看会发生什么。

让我们创建一个单元测试类来验证调用Connection.getSchema()方法是否会抛出AbstractMethodError

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