问题:Variable used in lambda expression should be final or effectively final
具体原因:
这段代码试图将 20 赋给一个局部变量,它无法通过编译,但绝非编写错误。
这实际上是语言的设计者有意为之,用以鼓励用户使用 Lambda 表达式获取值而不是变量。
获取值使用户更容易写出没有副作用的代码。
当我们在使用lambda表达式进行函数式编程时候,如何赋值局部变量是不允许的产生这样的原因是因为,lambda表达式是分为及早求值,惰性求值方法俩种方式,因为函数本身就是属于声明式类这样的方式,大大限制了函数内部的拓展使用。
如果一定要使用难免会加大程序的难度和使用,有问题后不易排查,当然这样的问题也不是没有办法,小杨告诉大家方法去处理。
实体类代码:
public static class TestJava8 {
private int id;
private String name;
private int age;
private int type;
public TestJava8(int id, String name, int age, int type) {
this.id = id;
this.name = name;
this.age = age;
this.type = type;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
使用代码:
//方法2参数
public static List result;
//方法1 参数
public List<TestJava8> result1;
@Test
public void main() {
//1 实际业务过滤返回的业务数据
TestJava8 testJava81 = new TestJava8(1, "张三", 20, 1);
TestJava8 testJava82 = new TestJava8(2, "李四", 30, 2);
List<TestJava8> list = new ArrayList<>();
list.add(testJava81);
list.add(testJava82);
AtomicReference<List<TestJava8>> listAtomicReference = new AtomicReference<>();
//2 过滤业务数据操作列入对接第三方平台去获取用户类型数据
list.stream().forEach(m -> {
//3 业务方法使用
TestJava8 testJava83 = new TestJava8(4, "王二", 30, 3);
TestJava8 testJava84 = new TestJava8(5, "张兰", 50, 4);
List<TestJava8> fliterList = new ArrayList<>();
fliterList.add(testJava83);
fliterList.add(testJava84);
//方法1使用
getTestJava8List(fliterList);
//方法2 使用
DataUtils.setResult(fliterList);
//方法3 使用
listAtomicReference.set(fliterList);
//方式4分布式缓存set
});
System.out.print("方法一获取:" + JSON.toJSONString(result1));
System.out.print("方法二获取:" + JSON.toJSONString(DataUtils.getResult()));
System.out.print("方法三获取:" + JSON.toJSONString(listAtomicReference.get()));
}
public static List<TestJava8> getResult() {
return result;
}
public static void setResult(List<TestJava8> result) {
DataUtils.result = result;
}
/**
* 方法一 使用获取
* @param list
* @return
*/
public List<TestJava8> getTestJava8List(List<TestJava8> list) {
result1 = list;
return result1;
}
解决方法一:
编写方法去接收,通过对象属性赋值的特性。
//定一一个集合
public List result;
/**
* 定义本地方法返回
* @param list
* @return
*/
public List getTestJava8List(List list) {
this.result =list;
return result;
}
解决方法二:定静态属性值
静态可以缓存到常量池里面,所以有一定缓存时间,其实这种就是jvm的本地缓存
public static List result;
public static List<TestJava8> getResult() {
return result;
}
public static void setResult(List<TestJava8> result) {
DataUtils.result = result;
}
获取:
//2 过滤业务数据操作列入对接第三方平台去获取用户类型数据
list.stream().forEach(m -> {
//3 业务方法使用
TestJava8 testJava83 = new TestJava8(4, "王二", 30, 3);
TestJava8 testJava84 = new TestJava8(5, "张兰", 50, 4);
List<TestJava8> fliterList = new ArrayList<>();
fliterList.add(testJava83);
fliterList.add(testJava84);
DataUtils.setResult(fliterList);
});
使用:
DataUtils.getResult();
解决方法三:通过cas无锁的机制,内存交换原子操作AtomicReference 通过这个存入数据,既能解决当前的问题,还能保证线程的数据安全问题,通常是用这个。
使用方式:
AtomicReference<List> listAtomicReference = new AtomicReference<>();
//2 过滤业务数据操作列入对接第三方平台去获取用户类型数据
list.stream().forEach(m -> {
//3 业务方法使用
TestJava8 testJava83 = new TestJava8(4, “王二”, 30, 3);
TestJava8 testJava84 = new TestJava8(5, “张兰”, 50, 4);
List fliterList = new ArrayList<>();
fliterList.add(testJava83);
fliterList.add(testJava84);
listAtomicReference.set(fliterList);
});
获取: listAtomicReference.get();使用即可
解决方法四:分布式缓存
使用分布式缓存,或者第三方缓存都是能够获取到参数值的,但是对数据的一致性要求不是那么高的时候我推荐使用第三种方式,如果对数据一致性要求比较高的话就使用分布式缓存,多个服务之间共享处理,如果是比较简单单体我推荐使用第一种方式,没有很多并发和请求。
————没有与生俱来的天赋,都是后天的努力拼搏(我是小杨,谢谢你的关注和支持)