在 Java 中显式调用默认方法

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

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

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


答案 1

根据本文,您可以使用界面访问默认方法A

A.super.foo();

这可以按如下方式使用(假设接口并且两者都有默认方法)ACfoo())

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
    }
}

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

方法调用语法的正式描述可以在 JLS 的第 15 章中找到。


答案 2

这个答案主要是为来自问题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();
    }
}

输出:

你好家长班!
你好界面Foo!
你好界面吧!


推荐