当前位置: 首页 > 面试题库 >

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

郎健柏
2023-03-14
问题内容

考虑下面的类层次结构。

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();
    }
}

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

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. 这是因为我将ClassA.hello标记为私有。
  2. 如果我将ClassA.hello标记为受保护或删除了可见性修饰符(即使其成为默认作用域),那么它将显示编译器错误为: The inherited method ClassA.hello() cannot hide the public abstract method in Myinterface

但是,按照上面的异常stacktrace, 我得到一个运行时IllegalAccessError。

我不明白为什么在编译时没有检测到这个。有什么线索吗?


问题答案:

更新: 似乎确实是一个 错误

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

default hello(...)中的方法Myinterface允许您编写无错误的内容:

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

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

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



 类似资料:
  • 问题内容: 如果我们需要实现两个接口,这两个接口都包含一个具有相同名称和参数但返回类型不同的方法,我们该怎么办?例如: 有没有简单的方法可以解决此问题? 问题答案: 最简单的解决方案是始终返回A,因为它可以存储所有可能的值。 如果您不是一个选择,则需要使用继承的替代方法。

  • 我试图使用以下代码理解Java接口中的默认方法,但我无法编译它: 编译器生成了以下输出: 我无法理解这些错误。我如何更正代码中的问题?

  • 我想通过创建一个具体实现类的对象来执行接口中默认方法的定义体,该对象也覆盖了该方法。无论我是直接创建具体实现类的对象,还是通过动态绑定/多态,实现类中定义/重写的主体都只是得到执行。请看下面的代码 我想知道如何在控制台内部界面银行打印以下内容--loan()

  • 在Java8中,如果我有两个具有不同(但兼容)返回类型的接口,反射告诉我这两个方法中的一个是默认方法,即使我实际上没有将该方法声明为默认方法或提供方法体。 例如,以以下代码段为例: Java 1.8生成以下输出: 这看起来很奇怪,不仅因为这两种方法都存在,还因为其中一种方法突然莫名其妙地变成了默认方法。 在Java7中运行相同的代码会产生一些不那么出乎意料的东西,尽管仍然令人困惑,因为这两个方法具

  • 在java 8之前,接口可以有以下类型的变量/方法。 常量变量 抽象方法 所以我们不能在接口中编写方法的实现,或者更确切地说,在Java 8之前实现默认实现。请参阅下面示例。 执行上面示例代码,得到以下结果 - 在上面的例子中,每个日志方法都有自己的实现。 使用Java 8接口可以有以下类型的变量/方法。 常量变量 抽象方法 默认方法 静态方法 让我们使用Java 8在接口中使用默认实现和静态方法

  • 最近我遇到了这段代码。 后来,它变成了这个项目的一般惯例。这是否被认为是一种良好的做法?