以下程式在編譯時期會出現錯誤訊息
interface Greeting {
void hi();
}
public static void main(String[] args) {
String name = "John";
name += " and Marry";
Greeting greeting = () -> {
System.out.println("Hello " + name);
};
greeting.hi();
}
原因
這好發於 Anonymous Inner Class
局部類別存取的外部變數
必須是 final 或等效於 final
而以上程式
Greeting 所存取的 name 變數
經過修改所以不符規定
解決辦法
傳入:重新引用
取得外部資料的部分不難
只要將修改的變數重新引用即可
在外部重新引用:
String name = "John";
String newName = name + " and Marry";
Greeting greeting = () -> {
System.out.println("Hello " + newName);
};
greeting.hi();
在內部重新引用:
String name = "John";
Greeting greeting = () -> {
String newName = name + " and Marry";
System.out.println("Hello " + newName);
};
greeting.hi();
傳出:使用容器
如果不只傳入資料
還要將運行後的結果返回給外部
就必須使用容器
例如以下程式
雖然重新引用可以在內部順利運作
但外部就無法取得加總後的結果
int sum = 0;
List<Integer> numbers = Arrays.asList(23, 45, 67, 89);
numbers.forEach(i -> {
sum += i;
});
System.out.println(sum);
可以藉由容器的存入取出
修改其中的資料
而容器本身是同一個
所以能實現內部外部的溝通
程式調整後如下:
List<Integer> sum = new ArrayList<Integer>();
sum.add(0);
List<Integer> numbers = Arrays.asList(23, 45, 67, 89);
numbers.forEach(i -> {
sum.set(0, sum.get(0) + i);
});
System.out.println(sum.get(0));
以上程式可以使用 AtomicInteger 達到相同效果
AtomicInteger sum = new AtomicInteger(0);
List<Integer> numbers = Arrays.asList(23, 45, 67, 89);
numbers.forEach(i -> {
sum.addAndGet(i);
});
System.out.println(sum.get());
其實也是物件承載的概念
但 java.util.concurrent.atomic.* 只限定某些類型
因此還是最泛用