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

隐藏接口的默认方法

张和豫
2023-03-14
问题内容

考虑以下情况,

interface IFace1 {
    default void printHello() {
        System.out.println("IFace1");
    }
}

interface IFace2 {
    void printHello();
}

public class Test implements IFace1, IFace2 {

    public static void main(String[] args) {
        Test test = new Test();
        test.printHello();

        IFace1 iface1 = new Test();
        iface1.printHello();

        IFace2 iface2 = new Test();
        iface2.printHello();
    }

    @Override
    public void printHello() {
        System.out.println("Test");
    }
}

在上面的例子中我得到以下输出这是 相当 期待。

Test
Test
Test

我一直在阅读有关Java-8默认方法的信息, 尤其是
关于扩展包含默认方法的接口的信息

2 第二子弹:重新声明的默认方法,这使得它的抽象。

在上面的示例中,我有两个接口的默认方法具有相同的名称,并且当我实现这两个接口时,我只能实现对printHelloTest引用IFace2

我对此几乎没有疑问,

  1. 我怎样才能 到达printHello方法IFace1 如果我不能比,为什么?
  2. 没有这种行为从本质上意的让我走IFace1 通过其他方法现在阴影?

Quote说,您可以在其子界面中创建该default方法abstract例如,

interface IFace2 extends IFace1 {
    void printHello();
}

在这里,当我实现时,我IFace2实际上将无法实现这种default方法,IFace1这正是我的情况。


问题答案:

似乎您对default方法的存在感到困惑。因此,让我们暂时忘记这IFace1.printHello()是一种default方法。因此,有一个明显的情况:Test实现两个接口IFace1IFace2,它们碰巧具有一个具有相同名称和签名的方法。

Test实现该方法,因此对两个接口都实现了该方法。default方法的新功能不会改变此逻辑。而且,语言设计者要注意,添加default方法不会影响现有代码的行为,因此,如果您的类实现了该方法,则方法的存在将default变得无关紧要。

但是,如果编写的代码知道方法的存在default,则可以调用它,如果它是由直接超级接口声明或继承的,即可以在代码IFace1.super.printHello()中调用的default方法IFace1

这些规则与超类的规则没有太大不同。如果更改接口以使接口IFace2扩展IFace1并仍声明printHello()abstract方法,则此abstract方法会覆盖该default方法,并且您将无法再IFace1.super.printHello()从内部进行调用Test

如前所述,这些规则与普通实例方法没有太大不同。如果Test声明了一个方法printHello(),那是 唯一的
,你可以通过一个参考调用方法Test的实例,其声明的类型,无论是TestIFace1还是IFace2。只有Test其自身的实现方法才可以执行super调用。

当涉及到接口的可能的多重继承时,主要区别就发挥了作用。如果你的类Test没有
实施该方法printHello(),它取决于两个接口的继承关系,会发生什么

  • 如果IFace2extends IFace1,它是抽象方法,则重新声明该default方法,因此会发生编译器错误,因为Test必须实现该abstract方法
  • 如果IFace2不扩展IFace1,则有两个具有相同名称和签名的可继承方法,因此Test将不会继承该default方法,并且会发生编译器错误,因为Test必须实现该abstract方法
  • 如果IFace1extends IFace2Test将继承该default方法。如果Test未实现IFace2,它也会继承它,但这应该令人惊讶……


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

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

  • 问题内容: 向所有Java专家致敬! 从Java8开始,我们可以在接口中使用默认实现(是的!)。但是,当您想从默认方法登录时会出现问题。 我有种感觉,每次我想在默认方法中记录某些内容时都调用.getLogger()是不明智的。 是的,可以在接口中定义静态变量-但这对于接口而言不是一个好习惯,而且+暴露了记录器(必须是公开的)。 我目前的解决方案: LogHolder仍然对所有人可见,这实际上没有任

  • 下面是一个简单的例子,展示了我的问题: 在中,我提供了方法和的实现,这是来自的唯一抽象方法。但是,当我编译时,我仍然会遇到以下错误: 类型MyWork必须实现继承的抽象方法AbstractCollection.size() 或者 我的任务。java:3:错误:MyTask不是抽象的,并且不重写AbstractList中的抽象方法get(int) (取决于编译器)。当然,我使用的是java 8。 所

  • 学习Java8默认方法。这个链接就像互联网上的其他资源一样说 在“最严格的意义上”,默认方法是一种倒退,因为它们允许你用代码“污染”你的接口。但它们提供了允许向后兼容的最优雅和最实用的方法。它使Oracle更容易更新所有集合类,也使您更容易为Lambda修改现有代码。 我的理解是Java8Dev/Designers在接口中提供了默认方法,这样所有实现类就不必不必要地重写相同的行为,从而提供了向后兼

  • JUnit Jupiter允许在接口default方法中声明@Test,@RepeatedTest,@ParameterizedTest,@ TestFactory,@TestTemplate,@BeforeEach和@AfterEach。如果测试接口或测试类用@TestInstance(Lifecycle.PER_CLASS)注解(请参阅测试实例生命周期),则可以在测试接口中的static方法或