在 Java 中显式调用默认方法

Posted

技术标签:

【中文标题】在 Java 中显式调用默认方法【英文标题】:Explicitly calling a default method in Java 【发布时间】:2021-10-07 01:37:04 【问题描述】:

Java 8 引入了default methods 以提供扩展接口的能力,而无需修改现有实现。

我想知道当某个方法已被覆盖或由于不同接口中的默认实现冲突而无法使用时,是否可以显式调用该方法的默认实现。

interface A 
    default void foo() 
        System.out.println("A.foo");
    


class B implements A 
    @Override
    public void foo() 
        System.out.println("B.foo");
    
    public void afoo() 
        // how to invoke A.foo() here?
    

考虑到上面的代码,你会如何从 B 类的方法中调用 A.foo()

【问题讨论】:

你能告诉我为什么你的 foo() 方法在你的接口 A 中有实现吗??。 @MaciejCygan 在 Java 8 中是允许的 【参考方案1】:

根据this article,您可以使用接口A 访问默认方法

A.super.foo();

这可以如下使用(假设接口AC都有默认方法foo()

public class ChildClass implements A, C 
    @Override    
    public void foo() 
       //you could completely override the default implementations
       doSomethingElse();
       //or manage conflicts between the same method foo() in both A and C
       A.super.foo();
    
    public void bah() 
       A.super.foo(); //original foo() from A accessed
       C.super.foo(); //original foo() from C accessed
    

AC 都可以具有 .foo() 方法,并且可以选择特定的默认实现,或者您可以使用一个(或两者)作为新的 foo() 方法的一部分。您还可以使用相同的语法来访问实现类中其他方法的默认版本。

方法调用语法的正式描述可以在chapter 15 of the JLS中找到。

【讨论】:

另请注意,如果A extends SomeOtherInterfaceSomeOtherInterfacedefault Type method(),那么您不能只从ChildClass 调用SomeOtherInterface.super.method()。您只能调用在ChildClassimplements 子句中枚举的接口的默认方法,而不是其父接口的方法。 @Suseika 好点,就像没有super.super.someMethod(); 一样(因为那太可怕了) @gvlasov 好点,但是如何从子接口访问父接口的默认方法,有可能吗?更新............是的可能,更具体的解释在这里***.com/a/24280376/3791156 @RichardTingle 完美回答! @tejasvi88 Interface.method() 将暗示Interface 中的静态方法。这是一种“超级”,所以超级部分可以说是最重要的【参考方案2】:

下面的代码应该可以工作。

public class B implements A 
    @Override
    public void foo() 
        System.out.println("B.foo");
    

    void aFoo() 
        A.super.foo();
    

    public static void main(String[] args) 
        B b = new B();
        b.foo();
        b.aFoo();
    


interface A 
    default void foo() 
        System.out.println("A.foo");
    

输出:

B.foo
A.foo

【讨论】:

我认为这是描述上述问题的最佳示例。谢谢【参考方案3】:

此答案主要是为来自问题45047550 的用户编写的,该问题已关闭。

Java 8 接口引入了多重继承的某些方面。默认方法具有已实现的函数体。要从超类调用方法,可以使用关键字super,但如果要使用超接口进行调用,则需要显式命名。

class ParentClass 
    public void hello() 
        System.out.println("Hello ParentClass!");
    


interface InterfaceFoo 
    public default void hello() 
        System.out.println("Hello InterfaceFoo!");
    


interface InterfaceBar 
    public default void hello() 
        System.out.println("Hello InterfaceBar!");
    


public class Example extends ParentClass implements InterfaceFoo, InterfaceBar 
    public void hello() 
        super.hello(); // (note: ParentClass.super could not be used)
        InterfaceFoo.super.hello();
        InterfaceBar.super.hello();
    
    
    public static void main(String[] args) 
        new Example().hello();
    

输出:

你好家长班! 你好 InterfaceFoo! 界面栏你好!

【讨论】:

【参考方案4】:

您不需要覆盖接口的默认方法。只需像下面这样调用它:

public class B implements A 

    @Override
    public void foo() 
        System.out.println("B.foo");
    

    public void afoo() 
        A.super.foo();
    

    public static void main(String[] args) 
       B b=new B();
       b.afoo();
    

输出:

A.foo

【讨论】:

OP 说:“当方法被覆盖时,[是否]可以显式调用该方法的默认实现”【参考方案5】:

是否要覆盖接口的默认方法取决于您的选择。因为 default 类似于类的实例方法,可以直接在实现类对象上调用。 (简而言之,接口的默认方法是由实现类继承的)

【讨论】:

【参考方案6】:

考虑以下示例:

interface I
    default void print()
    System.out.println("Interface");
    


abstract class Abs
    public void print()
        System.out.println("Abstract");
    



public class Test extends Abs implements I

    public static void main(String[] args) throws ExecutionException, InterruptedException 
    

        Test t = new Test();
        t.print();// calls Abstract's print method and How to call interface's defaut method?
     

【讨论】:

以上是关于在 Java 中显式调用默认方法的主要内容,如果未能解决你的问题,请参考以下文章

在 QT 中显式调用paintGL

C#:在实现的方法中显式指定接口

怎么证明未显式定义构造方法时,编译器会自动生成无参的构造方法?

私有成员是不是应该在惯用的 C# 中显式声明为私有? [关闭]

Java 继承中构造方法的执行顺序问题

我是不是需要在 grails 中显式刷新 GORM 保存调用?