如何在lambda表达式中调用外部变量

如何在lambda表达式中调用外部变量


先来看一下 lambda 表达式长啥样:

xxx ()-> xxx

忽略两个 xxx,关键在于中间的部分。


能访问外部变量吗

能。

能修改吗

也能。

但不是总能,有些情况就不行。

说一下原因:

变量分为 局部变量、实例变量、静态变量 这三种。
后两种合并起来叫 成员变量

局部变量 就不能修改。
为什么不能?

处于线程安全的考虑,Java做了限制或者说是约束。

如果修改了会怎么样?
看一段代码:

public void test() {
	int a = 0;
	List<Integer> list = new ArrayList<>();
	list.forEach(item -> {
		System.out.println(a); // 此行不会报错
	    a++; // 此行会报错
	});
}

System.out.println(a); 仅仅是访问,自然是可以的。
a++; 修改原值了,那就不行了,编译时就报错。

那为什么修改了会报错?

因为 a 是一个局部变量,存储在栈中,方法运行结束即销毁。
如果 lambda 表达式还没运行完,外面的 test 方法已经运行结束了,此时 a 已无,那就出问题了。
所以实际上调用 a 得到的只是一个值,而非内存地址。

而成员变量不一样,静态变量存储在方法区,实例变量一般存储在堆中,不是说你一个方法结束了就没了,因此可以修改。

我非要修改怎么办

教你个方法,代码改成这样:

AtomicInteger a = new AtomicInteger();
List<Integer> list = new ArrayList<>();
list.forEach(item -> {
    a.getAndIncrement();
});

为什么这样就没问题了?
AtomicInteger 是什么东西?

直译过来就是原子类,它创建的对象进行的操作都是原子性的,因此能够保证值的同步性。

AtomicInteger 的具体解释这里就不进行了,有兴趣可以自行研究。

String 类型的话建议直接使用 StringBuilder

实例化对象的话就更没有问题了。
但要记住一点,不要在后续过程中给实例化对象重新赋值新地址就行了。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值