AbstractMethodError en Java

1. Vue d'ensemble

Parfois, nous pouvons rencontrer AbstractMethodError au moment de l'exécution dans notre application. Si nous ne connaissons pas bien cette erreur, cela peut prendre un certain temps pour déterminer la cause du problème.

Dans ce didacticiel, nous examinerons de plus près AbstractMethodError . Nous comprendrons ce qu'est AbstractMethodError et quand cela peut arriver.

2. Introduction à AbstractMethodError

AbstractMethodError est levée lorsqu'une application tente d'appeler une méthode abstraite non implémentée.

Nous savons que s'il existe des méthodes abstraites non implémentées, le compilateur se plaindra en premier. Par conséquent, l'application ne sera pas du tout construite.

Nous pouvons nous demander comment nous pouvons obtenir cette erreur au moment de l'exécution?

Tout d'abord, voyons où AbstractMethodError s'inscrit dans la hiérarchie des exceptions Java:

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

Comme le montre la hiérarchie ci-dessus, cette erreur est une sous-classe de IncompatibleClassChangeError . Comme le nom de sa classe parente l'indique, AbstractMethodError est généralement renvoyé lorsqu'il existe des incompatibilités entre les classes compilées ou les fichiers JAR.

Ensuite, comprenons comment cette erreur peut se produire.

3. Comment cette erreur peut se produire

Lorsque nous construisons une application, nous importons généralement des bibliothèques pour faciliter notre travail.

Disons que, dans notre application, nous incluons une bibliothèque baeldung-queue . La bibliothèque baeldung-queue est une bibliothèque de spécifications de haut niveau, qui ne contient qu'une seule interface:

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

Aussi, pour utiliser l' interface BaeldungQueue , nous importons une bibliothèque d'implémentation BaeldungQueue : good-queue . La bibliothèque good-queue n'a également qu'une seule classe:

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

Maintenant, si good-queue et baeldung-queue se trouvent dans le classpath, nous pouvons créer une instance BaeldungQueue dans notre application:

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

Jusqu'ici tout va bien.

Un jour, nous avons appris que baeldung-queue a publié la version 2.0 et qu'elle est livrée avec une nouvelle méthode:

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

Nous voulons utiliser la nouvelle méthode size () dans notre application. Par conséquent, nous mettons à niveau la bibliothèque baeldung-queue de 1.0 à 2.0 . Cependant, nous oublions de vérifier s'il existe une nouvelle version de la bibliothèque good-queue qui implémente les modifications de l' interface BaeldungQueue .

Par conséquent, nous avons good-queue 1.0 et baeldung-queue 2.0 dans le classpath.

De plus, nous commençons à utiliser la nouvelle méthode dans notre application:

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

Notre code sera compilé sans aucun problème.

Cependant, lorsque la ligne queue.size () est exécutée au moment de l'exécution, une AbstractMethodError sera renvoyée . C'est parce que la bibliothèque good-queue 1.0 n'implémente pas la méthode size () dans l' interface BaeldungQueue .

4. Un exemple concret

Grâce au scénario simple BaeldungQueue et GoodQueue , nous pouvons avoir l'idée quand une application peut lancer AbstractMethodError.

Dans cette section, nous verrons un exemple pratique de AbstractMethodError .

java.sql.Connection est une interface importante dans l'API JDBC. Depuis la version 1.7, plusieurs nouvelles méthodes ont été ajoutées à l' interface de connexion , comme getSchema ().

La base de données H2 est une base de données SQL open source assez rapide. Depuis la version 1.4.192 , il a ajouté le support de la méthode java.sql.Connection.getSchema () . Cependant, dans les versions précédentes, la base de données H2 n'a pas encore implémenté cette méthode.

Ensuite, nous appellerons la méthode java.sql.Connection.getSchema () à partir d'une application Java 8 sur une ancienne base de données H2 version 1.4.191 . Voyons ce qui va se passer.

Créons une classe de test unitaire pour vérifier si l'appel de la méthode Connection.getSchema () lèvera 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()); } } 

Si nous exécutons le test, il passera, confirmant que l'appel à getSchema () lève AbstractMethodError .

5. Conclusion

Parfois, nous pouvons voir AbstractMethodError au moment de l'exécution. Dans cet article, nous avons discuté du moment où l'erreur se produit à travers des exemples.

Lorsque nous mettons à niveau une bibliothèque de notre application, il est toujours recommandé de vérifier si d'autres dépendances utilisent la bibliothèque et d'envisager de mettre à jour les dépendances associées.

D'un autre côté, une fois que nous sommes confrontés à AbstractMethodError , avec une bonne compréhension de cette erreur, nous pouvons résoudre le problème rapidement.

Comme toujours, le code source complet de l'article est disponible à l'adresse over sur GitHub.