看到一篇文章,里面详细介绍了如何在接口中使用 default 方法和 static 方法,转载一下.
原文链接
Static and Default Methods in Interfaces in Java
1.概述
Java 8 引入了几个新的特性,包括 lambda 表达式, 函数式接口(functional interfaces),方法引用(method references),Stream API, Optional 类, 以及接口中定义默认(default)方法和静态(static)方法,我们这边详细介绍如何在接口中使用默认方法和静态方法.
2.为什么接口中需要默认方法
和普通的接口方法一样,默认方法的默认作用域也是 public,不需要显式地声明.
和普通接口方法不同的是,默认方法需要在方法签名中使用 default 关键字,下面就是一个简单的默认方法声明:
public interface MyInterface {
// regular interface methods
default void defaultMethod() {
// default method implementation
}
}
那么接口中的默认方法在什么情况下会用到呢?
在实际开发中,一个接口往往会有多个实现类,如果后期我们往接口中添加一个方法,那么所有的实现类都会被强制性的要求实现新添加的方法,否则编译报错,一个两个实现类还能改一改,十个八个就太麻烦了.
这时就轮到默认方法登场了,实现类无需主动去实现它,就能直接访问,因而也就不需要修改所有实现类的代码了.
3.接口默认方法使用
Vehicle 接口
public interface Vehicle {
String getBrand();
String speedUp();
String slowDown();
default String turnAlarmOn() {
return "Turning the vehicle alarm on.";
}
default String turnAlarmOff() {
return "Turning the vehicle alarm off.";
}
}
Car 实现类
public class Car implements Vehicle {
private String brand;
// constructors/getters
@Override
public String getBrand() {
return brand;
}
@Override
public String speedUp() {
return "The car is speeding up.";
}
@Override
public String slowDown() {
return "The car is slowing down.";
}
}
测试类
public static void main(String[] args) {
Vehicle car = new Car("BMW");
System.out.println(car.getBrand());
System.out.println(car.speedUp());
System.out.println(car.slowDown());
System.out.println(car.turnAlarmOn());
System.out.println(car.turnAlarmOff());
}
可以看到测试类中的第6,7行可以直接调用接口中的默认方法,而无需实现类自己去实现.
默认方法的典型应用是无需修改实现类的代码,就能提供额外的功能.
4.多接口继承默认方法使用规则
在某些情况下,如果一个类实现了两个接口,并且这两个接口中都包含相同的默认方法,那么会发生什么情况呢?
我们另外定义一个接口 Alarm
public interface Alarm {
default String turnAlarmOn() {
return "Turning the alarm on.";
}
default String turnAlarmOff() {
return "Turning the alarm off.";
}
}
修改实现类 Car
public class Car implements Vehicle, Alarm {
// ...
}
这时,会发现编译报错,提示 Car inherits unrelated defaults for turnAlarmOn() from Vehicle and Alarm 错误.
原因是Car 类继承的两个接口 Vehicle 接口和 Alarm 接口中有相同的默认方法 turnAlarmOn(),如果调用的话,系统不知道该调用哪一个,所以报错.
这时我们就需要手动去重写 turnAlarmOn()方法和 turnAlarmOff() 方法,并指定调用哪个接口中的默认方法.
public class Car implements Vehicle, Alarm {
@Override
public String turnAlarmOn() {
return Vehicle.super.turnAlarmOn();
}
@Override
public String turnAlarmOff() {
return Alarm.super.turnAlarmOff();
}
}
5.接口静态方法
接口中除了可以声明默认方法,还可以定义和实现静态方法.
接口静态方法的使用需要以 接口名称.静态方法名称() 的形式调用.
比如定义一个静态方法:
public interface Vehicle {
// regular / default interface methods
static int getHorsePower(int rpm, int torque) {
return (rpm * torque) / 5252;
}
}
在实现类中调用静态方法
Vehicle.getHorsePower(2500, 480));
静态接口方法背后的思想是提供一个简单的机制,它允许我们将相关方法放在一个单独的地方而不必另外创建一个对象,这样可以提高代码的内聚度。
6.总结
在本文中,我们深入探讨了Java8中静态方法和默认方法的使用。乍一看,这个特性可能有点草率,特别是从面向对象的纯粹主义的角度来看。理想情况下,接口不应该封装行为,而应该只用于定义特定类型的公共API。
然而,当涉及到现有代码的向后兼容性时,静态方法和默认方法是一个很好的权衡。
PS.百度翻译还挺好用的.>_<