原文鏈接:https://liushiming.cn/2020/02/23/java-default-methods/
概述
Java8帶來了一些全新的特性,包括lambda表達式、函數接口、方法引用、流、可選方法、接口中的靜態方法和默認方法。
在本文中,我們將深入討論為什么java8接口新增了默認方法,如何使用默認方法,並討論一些有用的用例。
默認方法
在接口中用default
關鍵字定義接口的默認方法。普通接口方法是不能有實現的,默認方法必須有實現:
public interface MyInterface {
// 普通接口方法
default void defaultMethod() {
// 默認方法
}
}
為什么需要默認方法
在Java8之前,接口只能有抽象方法。如果不強制所有實現類創建新方法的實現,就不能向現有接口添加新功能。
Java8新增默認方法的原因非常明顯。
在一個典型的基於抽象的設計中,一個接口有一個或多個實現類。接口要新增方法,所有的實現都要新增這個方法的實現。否則就不滿足接口的約束。
默認接口方法是處理此問題的解決方案。在接口添加默認方法不需要修改實現類,接口新增的默認方法在實現類中直接可用。
默認方法的使用
定義MobilePhone接口,其中setTime,getLengthInCm為默認方法
interface MobilePhone {
/**
* 獲取手機品牌
*/
String getBrand();
/**
* 獲取手機顏色
*/
String getColor();
/**
* 獲取手機長度(毫米)
*/
Double getLength();
/**
* 設置手機時間
*/
default String setTime(String newTime) {
return "time set to " + newTime;
}
/**
* 對getLength方法進行拓展,返回厘米為單位的長度
*/
default String getLengthInCm() {
return getLength() / 10 + "cm";
}
}
默認方法在實現類中可以直接使用:
public class DefaultTests implements MobilePhone {
@Override
public String getBrand() {
return "iphone";
}
@Override
public String getColor() {
return "red";
}
@Override
public Double getLength() {
return 150.00;
}
@Test
public void defaultTest() {
System.out.println(setTime("8:00 am"));
System.out.println(getLengthInCm());
}
}
結果:
time set to 8:00 am
15.0 cm
如果在某個時候我們往接口添加更多的默認方法,實現類可以不用修改繼續使用。
默認方法的最典型用法是逐步為接口提供附加功能,而不破壞實現類。
此外,它們還可以用來為現有的抽象方法提供額外的功能:
interface MobilePhone {
/**
* 獲取手機長度(毫米)
*/
Double getLength();
/**
* 對getLength方法進行拓展,返回厘米為單位的長度
*/
default String getLengthInCm() {
return getLength() / 10 + "cm";
}
}
默認方法的多繼承
Apple接口和Samsung接口繼承MobilePhone接口:
interface Apple extends MobilePhone {
@Override
default String setTime(String newTime) {
return "time set to " + newTime + " in apple";
}
}
interface Samsung extends MobilePhone {
@Override
default String setTime(String newTime) {
return "time set to " + newTime + " in samsung";
}
}
DefaultTests實現Apple和Samsung接口,必須對setTime
方法進行重寫,否則對象將不知道該使用Apple的setTime方法還是Samsung的setTime方法,因為它們同名了
public class DefaultTests implements Apple, Samsung {
@Override
public String getBrand() {
return "iphone";
}
@Override
public String getColor() {
return "red";
}
@Override
public Double getLength() {
return 150.00;
}
@Override
public String setTime(String newTime) {
return Apple.super.setTime(newTime);
}
@Test
public void defaultTest() {
System.out.println(setTime("8:00 am"));
System.out.println(getLengthInCm());
}
}
結果
time set to 8:00 am in apple
15.0 cm
總結
在本文中,我們深入探討了Java8中接口默認方法的使用。乍一看,這個特性可能有點馬虎,特別是純粹從面向對象的角度來看。理想情況下,接口不應該封裝行為,而應該只用於定義特定類型的公共API。
但是在維護現有代碼的向后兼容性時,靜態方法和默認方法是一種很好的折衷。