首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 7 閉包與 Lambda 表達式初探:語法優劣與 Checked Exception 挑戰

     編輯:Java 相關知識

兩種 Lambda 語法形式

Oracle 釋出的 Java 7 原型實現提供兩種寫法:

表達式形式(單一運算式)

#int() func1 = #()(3); #int(int) func2 = #(int x)(x + 1); #int(int, int) func3 = #(int x, int y)(x - y);

區塊形式(多行敘述)

#int() func1 = #{ return 3; }; #int(int) func2 = #(int x){ return x + 1; }; #int(int, int) func3 = #(int x, int y){ return x - y; };

與 C# Lambda 比較

特性Java 7C#
參數/主體分隔無=>
單一運算式括號必要可省略
單參數括號必要可省略
類型推論僅回傳值與異常參數、回傳皆支援

範例:對使用者陣列按年齡排序

// C#: users.Sort(u => u.Age); // Java: Arrays.sort(users, #(User u)(u.Age));

C# 更具宣告式可讀性;Java 顯得冗贅。

SAM 單一抽象方法類型支援

Java 允許 Lambda 直接轉換為具單一抽象方法的介面(如 Func),無需預先定義 Delegate 類型,較 C# 靈活:

Func[] arr = new Func[10]; for(int i=0;i

閉包捕獲語義與 this 歧義

Lambda 內部存取變數優先順序:目標 SAM 類型成員 > 詞法作用域成員。範例:

public class MyClass { public int n = 3; public void m() { Func f = #(int x)(x + n); // 捕獲 MyClass.n } public int hashCode() { throw new RuntimeException(); } public void test() { Func f = #(int x)(x * hashCode()); // 呼叫 Func.hashCode(),不拋出 // 需寫 MyClass.this.hashCode() 才呼叫外部方法 } }

此設計雖相容既有 SAM API,但與主流語言詞法捕獲語義不同,易產生困惑。

硬傷:Checked Exception 對 Lambda 的衝擊

Java 受檢異常強制方法宣告 throws,導致函數式介面難以通用:

// 無法編譯:getCanonicalPath() 拋 IOException map(files, #(String f)(new File(f).getCanonicalPath()));

若介面不宣告 throws IOException,Lambda 無法拋出;若宣告,則介面綁定特定異常,失去通用性。Java 雖支援異常類型推論,但根本衝突未解。Scala/Groovy 棄用 Checked Exception 即為佐證。

其他特性

  • 參數泛化:#boolean(Integer) f = #(Number n)(n.intValue() > 0);
  • 與 MethodHandle 互轉。

結語

Java 7 Lambda 在 SAM 相容性上有實用價值,但語法冗長、缺乏參數類型推論、Checked Exception 成為函數式編程絆腳石,整體優雅度不及 C#/Scala。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved