Lambda 程序中的應用
通過前面的內容我們對于 Lambda 表達式以及函數(shù)式編程已經(jīng)有了一定的了解,對于集合方面的使用也有了概念,那么,在本節(jié)我們將從一個日志改造的例子出發(fā),探討下如何在我們的程序中更好地使用 Lambda 表達式。
Tips: 本節(jié)內容有點分散,主要是啟發(fā)大家的思路
1. 讓我們的類支持 Lambda 表達式
日志記錄工具是我們平時用的最多的一個工具,比如 SLF4J、Log4j 等,可以幫助我們快速查看程序的信息、定位問題,也在一定程度上增加了系統(tǒng)開銷,通常我們在寫 debug
日志的時候為了降低會進行日志級別的判定 (在本例中我們使用的是 Log4j 2)
public class DemoLogger {
public static void main(String[] args) {
Logger logger = LogManager.getLogger(DemoLogger.class);
if(logger.isDebugEnabled()){
logger.debug("這是一個debug日志");
}
}
}
想必上面的代碼應該都非常熟悉,在 Log4j 2 中提供了 Lambda 表達式實現(xiàn)的日志記錄方法,對于上述代碼我們可以簡化為:
public class DemoLogger {
public static void main(String[] args) {
Logger logger = LogManager.getLogger(DemoLogger.class);
logger.debug(()->"這是一個debug日志");
}
}
通過查看源代碼我們可以發(fā)現(xiàn) Logger 對象提供了一個 Supplier 的 debug
方法:
@Override
public void debug(final Supplier<?> msgSupplier) {
logIfEnabled(FQCN, Level.DEBUG, null, msgSupplier, (Throwable) null);
}
@Override
public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final Supplier<?> msgSupplier,
final Throwable t) {
if (isEnabled(level, marker, msgSupplier, t)) {
logMessage(fqcn, level, marker, msgSupplier, t);
}
}
在這個方法中,它通過 logIfEnabled
判斷是否為 debug
進而決定是否調用 supplier
對象的內容。 這給了我們一個啟發(fā),那就是:
我們可以運用
java.util.funciton
中的接口來重新封裝我們原有的類來支持 Lambda 表達式,進而簡化我們的代碼。
2. 多重繼承
在 Java 中接口是允許多重繼承的,那么如果多個接口有著相同的默認方法的情況下會怎么樣呢?
public class MultipleInterface {
public interface RedBox{
public default String color(){
return "red";
}
}
public interface BlueBox{
public default String color(){
return "blue";
}
}
public class CombineBox implements RedBox,BlueBox{
}
}
在上面的代碼中,我們定義了兩個接口 RedBox
和 BlueBox
都有相同的默認方法 color
,類 CombineBox
同時實現(xiàn) RedBox
和 BlueBox
,此時,由于編譯器不清楚應該繼承哪個接口,所以報錯:
MultipleInterface.CombineBox inherits unrelated defaults for color() from types MultipleInterface.RedBox and MultipleInterface.BlueBox
此時,我們可以使用同方法重載來明確方法內容,當然我們可以通過 super
語法來給編譯器明確使用哪一個默認接口:
public class CombineBox implements RedBox,BlueBox{
public String color(){
return RedBox.super.color();
}
}
上述的內容我們主要是對默認方法的工作原理做了一個簡單的介紹,對于默認方法通常有三條定律來幫助我們使用默認方法:
- 類勝于接口:如果在繼承鏈中有聲明的方法,那么就可以忽略接口中定義的方法 (這樣可以讓我們的代碼向后兼容);
- 子類勝于父類:如果一個接口繼承了另外一個接口,而且兩個接口都定義了一個默認方法,那么子類中定義的方法將生效;
- 如果上述兩條都不適用,那么子類要么需要實現(xiàn)該方法,要么將該方法聲明成抽象方法 (
abstract
)。
小結

本節(jié)從類的重新和接口繼承兩方面介紹了我們如何重新封裝我們的類來支持 Lambda 表達式,以及在函數(shù)接口在多繼承的情況下出現(xiàn)默認方法沖突時如何去編寫我們的代碼。大家可以在平時的編碼過程中按照上述的思路逐步練習封裝自己原來的代碼,自然就會有自己的心得體會。