使用Lambda訪問外部變量
Lambda表達式,可以像下面這樣,在其函數體內訪問外部的變量。
public class Closure {
private String abc = "abc";
public String joinStr(String str, UnaryOperator<String> unaryOperator){
return unaryOperator.apply(str);
}
public void useJoinStr(String str){
String prefix = "log:";
String result = joinStr(str,s -> {
return prefix+s;
});
System.out.println(result);
}
public static void main(String[] args) {
Closure closure = new Closure();
closure.useJoinStr("this is a test");
}
}
在函數useJoinStr中,調用joinStr,傳入字符串的同時,傳遞一個Lambda,這個Lambda完成一個工作,就是給字符串增加一個“log:”的前綴。這里前綴定義為函數useJoinStr的局部變量,執行main函數得到結果
log:this is a test
這是我們預期的結果,但是要注意一點,Java編譯器要求,Lambda引用的外部變量如果是局部變量,該變量應該是,或實際意義上是final的,也就是該變量不能被改變。如果我們在prefix定義之后修改變量的內容,會引起編譯錯誤,無論在使用前還是使用后
例如:
public void useJoinStr(String str){
String prefix = "log:";
prefix = "loog:";
String result = joinStr(str,s -> {
return prefix+s;
});
System.out.println(result);
}
這里在定義完prefix后,又修改它的值,編譯直接就報錯了,不允許這樣的代碼,也可以將該變量修飾為final的。這是Lambda對訪問外部的局部變量的要求,使用時需要注意。
但是,Lambda對於使用實例變量和靜態變量是沒有限制的,下面的代碼是有效的。
public void useJoinStr(String str){
final String prefix = "log:";
abc = "log:";
String result = joinStr(str,s -> {
return abc+s;
});
System.out.println(result);
}
這里,修改了對象的私有變量abc,並在lambda中使用該變量,程序可以正常編譯,並得到正確的結果。