关于Lambda表达式里面修改外部变量问题

时间:2024-11-15 16:03:53

        因为平台用的是JDK8,而且发现自己对那些新特性好像一点都不了解,就例如Lambda表达式,所以就开始对自己的代码进行改进了。。。

        例如遍历Map,像我们正常遍历肯定是下面这样子的。

String result = "select * from where id = '#userId#' and name = '#userName#'";
Map<String,String> sysParams = new HashMap<String,String>();
("#userId#", "userId");
("#userName#", "userName");
("#realName#", "realName");
("#orgIds#", "orgIds");
("#departname#", "departname");
("#roleId#", "roleId");

for(<String, String> entry : ()){
	if(result .contains(())){
		result = result .replaceAll((), (()));
	}
}

但是如果用Lambda表达式呢,将会非常的简单,

但是我们会发现,result那里是会报错的:Local variable result defined in an enclosing scope must be final or effectively final

String result = "select * from where id = '#userId#' and name = '#userName#'";
Map<String,String> sysParams = new HashMap<String,String>();
("#userId#", "userId");
("#userName#", "userName");
("#realName#", "realName");
("#orgIds#", "orgIds");
("#departname#", "departname");
("#roleId#", "roleId");
		
((key,value)->{
	if((key)){
		result  = (key, value);
				
	}
});

这是因为:Java会将result的值作为参数传递给Lambda表达式,为Lambda表达式建立一个副本,它的代码访问的是这个副本,而不是外部声明result变量。可能很多同学会问为什么非要建立副本呢,直接访问外部的result变量得多方便呢。答案是:这是不可能滴,因为result定义在栈中,当Lambda表达式被执行的时候,result可能已经被释放掉了。

当然啦,你要是一定要在Lambda表达式里面修改外部变量的值也是可以的,可以将变量定义为实例变量或者将变量定义为数组。

下面我就改为数组咯,实例变量不方便。

	String result = "select * from where id = '#userId#' and name = '#userName#'";
	//将变量定义为数组就好了
    String[] arr = new String[]{result};
	Map<String,String> sysParams = new HashMap<String,String>();
	("#userId#", "userId");
	("#userName#", "userName");
	("#realName#", "realName");
	("#orgIds#", "orgIds");
	("#departname#", "departname");
	("#roleId#", "roleId");
		
	((key,value)->{
		if(arr[0].contains(key)){
            //都是对数组进行操作了
			arr[0]  = arr[0].replaceAll(key, value);
				
		}
	});