web-dev-qa-db-fra.com

Appel de la méthode par défaut dans l'interface en cas de conflit avec une méthode privée

Considérez ci-dessous la hiérarchie des classes.

class ClassA {
    private void hello() {
        System.out.println("Hello from A");
    }
}

interface Myinterface {
    default void hello() {
        System.out.println("Hello from Interface");
    }
}

class ClassB extends ClassA implements Myinterface {

}

public class Test {
    public static void main(String[] args) {
        ClassB b = new ClassB();
        b.hello();
    }
}

L'exécution du programme donnera l'erreur suivante:

Exception in thread "main" Java.lang.IllegalAccessError: tried to access method com.testing.ClassA.hello()V from class com.testing.Test
at com.testing.Test.main(Test.Java:23)
  1. C'est tout parce que j'ai marqué ClassA.hello comme privé.
  2. Si je marque ClassA.hello comme protégé ou que je supprime le modificateur de visibilité (c'est-à-dire ce qui en fait l'étendue par défaut), alors il affiche une erreur de compilation comme: The inherited method ClassA.hello() cannot hide the public abstract method in Myinterface

Cependant, conformément à la trace de pile d'exceptions ci-dessus, j'obtiens une erreur d'exécution IllegalAccessError.

Je n'ai pas pu comprendre pourquoi cela n'est pas détecté au moment de la compilation. Des indices?

39

Mise à jour: On dirait que c'est vraiment un bogue =.

Une déclaration de méthode de classe ou de super-classe a toujours la priorité sur une méthode par défaut!

La méthode default hello(...) de Myinterface vous permet d'écrire sans erreur:

ClassB b = new ClassB();
b.hello();

Jusqu'à l'exécution, car à l'exécution, la méthode hello(...) de ClassA a la priorité la plus élevée (mais la méthode est privée). Par conséquent, IllegalAccessError se produit.

Si vous supprimez la méthode par défaut hello(...) de l'interface, vous obtenez la même erreur d'accès illégal, mais maintenant au moment de la compilation.

29