1. 程式人生 > 實用技巧 >Java函數語言程式設計

Java函數語言程式設計

Java函數語言程式設計

匿名內建類

使用場景

Java作為一門面向物件的靜態語言,其封裝效能夠遮蔽資料結構的細節,從而更加關注模組(功能)的功能性。其靜態性也確保了Java強型別的特性。隨著模組功能的提升,伴隨而來的是複雜度的增加,程式碼的語義清晰依賴於開發人員的抽象(通用)和命名類或方法能力。儘管程式設計思想和設計模式能夠促使程式設計風格趨於統一,然而大多數業務系統屬於面向過程的方式(增刪改查,輸入輸出),這與面向物件程式設計在一定程度上存在一些衝突。Java程式語言為了解決這個問題,引入了匿名內建類的方案

  • 經典使用場景

    • Java Event/Listener

    • Java Concurrent

    • Spring Template

基本特徵

  • 無名稱類

  • 宣告位置(執行模組):

    ​ static block

      // Static 塊
    static {
    new Runnable() {
    @Override
    public void run() {
    }
    };
    }

    ​ 例項block

      
    // 例項塊
    {
    new Callable() {
    @Override
    public Object call() throws Exception {
    return null;
    }
    };
    }

    ​ 方法

      
    // 方法(類或例項)
    PropertyChangeListener listener = new PropertyChangeListener() {
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
    }
    };

    ​ 構造器

      // 構造器
    public InnerClassDemo() {
    new Comparable(){

    @Override
    public int compareTo(Object o) {
    return 0;
    }
    };
    }
  • 並非特殊的類結構

    類全名稱:$${package}.${declared_class}.${num}

基本特點

  • 基於多型(多數基於介面程式設計) 如Runnable,Callable

  • 實現類無需名稱

  • 允許多個抽象方法

  
new KeyListener(){
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
};

程式設計侷限

  • 程式碼臃腫強制型約束 如:Runnable,Callable都指定了一型別

  • 介面方法升級

Lambda表示式

基本特點

  • ​ 流程編排清晰

  • ​ 函式型別程式設計

  • ​ 改善程式碼臃腫​ 相容介面升級

實現手段

  • ​ @FunctionalInterface介面 宣告函式式介面,並不一定要打這個註解,只要滿足約束它就是函式式介面,有且只有一個抽象方法

Lambda語法

  
// 匿名類 傳統寫法
PropertyChangeListener listener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
println(evt);
}
};

// Lambda 基本寫法
PropertyChangeListener listener2 = evt -> {
println(evt);
};

方法引用

  
// Lambda 簡略寫法
// PropertyChangeListener#propertyChange(PropertyChangeEvent)
// 屬於有入參,沒有返回,與 println(Object) 一樣
PropertyChangeListener listener3 = LambdaDemo::println;

四種模式

SCFP = Supplier + Consumer + Function + Predicate

  
public class LambdaDemo {
// SCFP = Supplier + Consumer + Function + Predicate
// 四種模式(缺少 Action 模式)
// Action 模式
private static void showAction() {
Runnable runnable = new Runnable() {
@Override
public void run() {
}
};
Runnable runnable2 = () -> {
};
Runnable runnable3 = LambdaDemo::showConsumer;
}
// Supplier 模式
private static void showSupplier() {
String string = "Hello,World";
Supplier<String> string2 = () -> "Hello,World";
Supplier<String> string3 = () -> new Integer(2).toString();
}
// Consumer 模式
private static void showConsumer() {
// 匿名類 傳統寫法
PropertyChangeListener listener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
println(evt);
}
};

// Lambda 基本寫法
PropertyChangeListener listener2 = evt -> {
println(evt);
};

// Lambda 簡略寫法
// PropertyChangeListener#propertyChange(PropertyChangeEvent)
// 屬於有入參,沒有返回,與 println(Object) 一樣
PropertyChangeListener listener3 = LambdaDemo::println;
}

// Function 模式
private static void showFunction() {
Function<String, Integer> f = LambdaDemo::compareTo;
}

private static Integer compareTo(String value) {
return value.compareTo("Hello,World");
}
public static void main(String[] args) {
Action a = () -> {
};
}
private static void println(Object object) {
System.out.println(object);
}
@FunctionalInterface
public interface Action {
void execute();
default void doExecute() {
execute();
}
}
private static void stream() {
Stream.of(1, 2, 3, 4, 5)
.map(String::valueOf)
;
}
}

程式設計侷限

  • ​ 單一抽象方法

    ​ Lambda除錯困難

    ​ Stream API 操作能力有限