Java8特性之接口的默认方法与静态方法


简介

     Java 8用默认方法与静态方法这两个新概念来扩展接口的声明。 它允许添加新方法到已有接口中,但是不会破坏那些基于老版接口实现的代码的二进制兼容性。 默认方法和抽象方法的区别在于:抽象方法是必须要实现的,而默认方法不是。

意义

众所周知,我们应该使用接口编程,接口使得在交互时不需要关注具体的实现细节,从而保持程序的松散耦合。在API的设计中,设计简约而清晰的接口非常重要。被称作固定定律的接口分离定律,其中有一条就讲到了应该设计更小的特定客户端接口而不是一个通用目的的接口。良好的接口设计是让应用程序和库的API保持简洁高效的关键。如果你曾有过接口API设计的经验,那么有时候你会感觉到为API增加方法的必要。

举个例子,假设你设计了一个简单的API Calculator,里面有add、subtract、devide和multiply函数。 为了实现Calculator这个接口,需要写如下一个BasicCalculator类。如果 Calculator这个API非常简单实用,其他开发者只需要创建一个BasicCalculator就可以使用这个API。 然而,对于多个开发者来说,事实上给人的感觉却是此API的用户并不是面向这个接口进行编程,而是面向这个接口的实现类在编程。
如果我们使用默认方法,这样,用户就被强制要求对Calculator接口进行编程,并且不需要关注接口的详细实现。

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private interface Defaulable {
     // Interfaces now allow default methods, the implementer may or
     // may not implement (override) them.
     default String notRequired() {
         return "Default implementation" ;
     }       
}
         
private static class DefaultableImpl implements Defaulable {
}
     
private static class OverridableImpl implements Defaulable {
     @Override
     public String notRequired() {
         return "Overridden implementation" ;
     }
}

Defaulable接口用关键字default声明了一个默认方法notRequired(),Defaulable接口的实现者之一DefaultableImpl实现了这个接口,并且让默认方法保持原样。Defaulable接口的另一个实现者OverridableImpl用自己的方法覆盖了默认方法。

Java 8带来的另一个有趣的特性是接口可以声明(并且可以提供实现)静态方法。例如:

1
2
3
4
5
6
private interface DefaulableFactory {
     // Interfaces now allow static methods
     static Defaulable create( Supplier< Defaulable > supplier ) {
         return supplier.get();
     }
}

下面的一小段代码片段把上面的默认方法与静态方法黏合到一起。

1
2
3
4
5
6
7
public static void main( String[] args ) {
     Defaulable defaulable = DefaulableFactory.create( DefaultableImpl:: new );
     System.out.println( defaulable.notRequired() );
         
     defaulable = DefaulableFactory.create( OverridableImpl:: new );
     System.out.println( defaulable.notRequired() );
}

这个程序的控制台输出如下:

1
2
Default implementation
Overridden implementation

在JVM中,默认方法的实现是非常高效的,并且通过字节码指令为方法调用提供了支持。默认方法允许继续使用现有的Java接口,而同时能够保障正常的编译过程。这方面好的例子是大量的方法被添加到java.util.Collection接口中去:stream(),parallelStream(),forEach(),removeIf(),……

尽管默认方法非常强大,但是在使用默认方法时我们需要小心注意一个地方:在声明一个默认方法前,请仔细思考是不是真的有必要使用默认方法,因为默认方法会带给程序歧义,并且在复杂的继承体系中容易产生编译错误。更多详情请参考官方文档


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值