与私有方法冲突时在接口中调用默认方法

Sha*_*war 39 java java-8 default-method

考虑以下类层次结构.

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

运行该程序将出现以下错误:

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)
Run Code Online (Sandbox Code Playgroud)
  1. 这都是因为我将ClassA.hello标记为私有.
  2. 如果我将ClassA.hello标记为protected或删除可见性修饰符(即使其成为默认范围),则它会显示编译器错误: The inherited method ClassA.hello() cannot hide the public abstract method in Myinterface

但是,根据上面的异常堆栈跟踪,我得到一个运行时IllegalAccessError.

我无法理解为什么在编译时没有检测到这一点.有线索吗?

Ole*_*hov 29

更新:似乎它真的是一个错误.

类或超类方法声明始终优先于默认方法!

default hello(...)从方法Myinterface可以让你没有错误写:

ClassB b = new ClassB();
b.hello();
Run Code Online (Sandbox Code Playgroud)

直到运行时,因为在运行时hello(...)方法从ClassA最高优先级(但方法是私有的).因此,IllegalAccessError发生.

如果hello(...)从界面中删除默认方法,则会出现相同的非法访问错误,但现在在编译时.

  • 哦,这是一个错误!我无法在JLS中找到任何非常相关的内容 (3认同)