在lambda中使用外部變量的一些心得

        隨着java8的普及,越來越多的人開始使用lambda表達式。然後初學者們總會遇到一個奇怪的問題:

        Variable used in lambda expression should be final or effectively final

        這個錯的產生的原因是因爲在lambda表達式中訪問外部變量時,都不允許有修改變量的傾向,即

        1、變量必須是final類型的

        2、如果沒有定義成final,那麼變量在初始化以後,不允許再有任何賦值的情況出現。(其實就是隱式final限制)

        這種情況的具體原因本文不討論,百度一大堆解釋,本次主要討論如果有非final變量,如何在lambda中使用。

方法一:

        這是我最初遇到該類問題時的解決辦法,就是不用lambda,改爲普通寫法。如將forecah循環改爲Iterator模式,這種方法一勞永逸。

方法二:

        利用list特性,地址不變,value可變。

List<User> a=new ArrayList<>();
boolean flag=true;
Set<Boolean> flagList =new HashSet<>();
a.forEach(item->{
	if(item.getAge()>18) {
		//Local variable flag defined in an enclosing scope must be final or effectively final
        //flag=false;
        flagList.add(false);
	}
	if(item.getName().equals("zhangsan")) {
		flagList.add(false);
	}
});
if(flagList.contains(false)) {
	return false;
}

        如上,可能例子不太好。之前公司的代碼是,要對list中所有的對象進行規則校驗,20多種情況。在寫完以後才發現需要返回是否全部通過,這時改成迭代器模式就太麻煩了,於是就採用了這種方式返回。

方法三:

        有時我們會遇到另一種情況,定義一個value=0,當type=1的時候,value=100。並且這種情況不需要在foreach中反覆處理,可以採用封裝方法的方式實現。

    public static void main(String[] args) {
		List<User> a=new ArrayList<>();
		int value=0;
		if(true) {
			value=100;
		}
		int lambdaValue=getValue(true);
		a.forEach(item->{
			//Local variable flag defined in an enclosing scope must be final or effectively final
//			item.setAge(value);
			item.setAge(lambdaValue);
		});
		
	}
	
	static int getValue(boolean flag) {
		return flag?100:0;
	}

方法四:

        這個方法是方法三的變種,就是在之前處理完value後,將value再賦值給lambdaValue。

    List<User> a=new ArrayList<>();
		int value=0;
		if(true) {
			value=100;
		}
		int lambdaValue=value;
		a.forEach(item->{
			//Local variable flag defined in an enclosing scope must be final or effectively final
//			item.setAge(value);
			item.setAge(lambdaValue);
		});

        方法三和方法四可以根據實際情況來選擇。

 

以上是個人工作中總結的一些方法,以後遇到新的方法會來補充,如果有人有更好的解決辦法,也請指出,謝謝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章