[转载] Java-forEach增强for循环是值传递规则详解
参考链接: Java中的for-each循环
1. 引入
正如Java语法意义,变量的传递只有值传递,虽然变量分为引用变量和基本类型变量,前者更像C中的地址概念。 在学习Lambda表达式的时候,遇到了试图在增强for循环中对原链表元素重新赋值失败的问题,网络上也没有针对此的其他博文,故开此文。
2. 数组的增强for循环
public class Test1{
public static void main(String[] args) {
int[] arr = new int[10];
for (int temp :arr){
temp++;
}
for (int temp :arr){
System.out.println(temp);
}
}
}
控制台会打出10个0,而不是1,这表明在forEach语句中temp++操作对arr数组本身没有任何影响,所以间接证明了,增强for循环中只是值传递。这也可以从原理层面解释:增强for循环作为一个语法糖,其执行顺序是:对数组第一个元素复制给临时变量temp,然后让temp执行循环中的语句;接着对数组第二个元素再次赋值给临时变量temp,再次让其执行for循环中的语句…就这般执行至数组最后一个元素。所以说,temp接受了数组元素的值,在++,这对于数组中的数字没有任何影响。所以说如果要进行原数组的更改,更好的方式是使用普通的for循环。
3. ArrayList的增强for循环
代码需求是将其list中的String类型对象从小写转换为大写;
public class LowercaseToUppercase{
public static void main(String[] args) {
List<String> list = Arrays.asList("hello", "world", "hello world");
list.forEach(i -> {
i = i.toUpperCase();
});
list.forEach(System.out::println);
}
}
控制还是输出小写的String类型对象,“hello”, “world”, “hello world”,倘若你查看forEach方法,你可以发现此原理和第一个例子的数组遍历实现原理是一样的,i作为一个中间变量,是临时存放了String类型的引用变量,但是对原list没有任何影响,如下面被调用的forEach方法的默认实现代码(其中t就是被定义为泛型类型T的临时变量)。 一个易错点:很多人认为:因为String内部是final修饰的数组,不能被重新赋值,临时变量i只能指向新的引用对象,所以上述代码功能才不能被实现,这是不对的,其真正的原因是对临时变量赋值是无法达到预期效果。正确的理解是:对临时变量进行赋值,只能使临时变量指向新的对象,而对原String对象没有任何作用。即使将上述代码中ArrayList的对象类型由String换成StringBuilder类,在这样的情况下,虽然同一个```StringBuilder``对象的值是可以被修改的,但是使用对临时变量赋值的操作还是不能对原数据结构元素值造成影响。
如果要实现,需要调用StringBuilder类对象的方法,一般是返回this对象,代码如下所示:
public class LowercaseToUppercase {
public static void main(String[] args) {
List<StringBuilder> list3= Arrays.asList(new StringBuilder("hello"),
new StringBuilder("world"),new StringBuilder("hello world"));
list3.forEach(i->
{
String str= i.toString().toUpperCase();
i.replace(0,str.length(),str);
}
);
list3.forEach(System.out::println);
}
}
控制台输出了大写的字符串,说明我们成功将StringBuilder类型由小写转化为大写,不过遍历中的临时变量i的赋值语句并不存在,而是调用其方法,返回this对象,才实现了转换。
下面这个代码块是Java集合的forEach方法默认实现,一定要读懂它:
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
可见Java在foreach语言的执行上保证了原数据结构的安全性,如果确定要更改原数据结构,请使用传统的for循环。并且我们在foreach语句中可以采用复制给新数据结构的方法实现类似的作用:
List<String> list2 = new ArrayList<>();
list.forEach(item->list2.add(item.toUpperCase()));
list2.forEach(System.out::println);
倘若返回list2,那么和传统的for语句也是类似的效果。
[转载] Java-forEach增强for循环是值传递规则详解相关推荐
- java foreach和for循环区别_java相关:老生常谈foreach(增强for循环)和for的区别
java相关:老生常谈foreach(增强for循环)和for的区别 发布于 2020-8-18| 复制链接 下面小妖就为大家带来一篇老生常谈foreach(增强for循环)和for的区别.小妖觉得挺 ...
- foeeach 和for效率java_老生常谈foreach(增强for循环)和for的区别
首先说一下foreach有的也叫增强for循环,foreach其实是for循环的一个特殊简化版. 再说一下foreach的书写格式: for(元素类型 元素名称 : 遍历数组(集合)(或者能进行迭代 ...
- java return返回值_java中关于return返回值的用法详解
我们输入一个条件时,系统就会对这个条件进行判断,然后给出一个返回时的结论,我们把这个结果看做是返回值.在java里可以使用return语句来进行返回,从字面意思就能很好的理解它的用法了.下面我们就re ...
- java 接口 返回值_java api返回值的标准化详解
api返回值的标准化 例如 {"status":200,"message":"操作成功","data":"{\ ...
- java switch 值_Java switch多值匹配操作详解
这篇文章主要介绍了Java switch多值匹配操作详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 我们都知道 switch 用来走流程分支,大 ...
- java int 传引用吗_Java值传递还是引用传递?
从我实习面试开始就有在面试中遇到过这个问题:Java是值传递还是引用传递? 当时的我只会背背面试题,但是网上的答案有些还是错的,导致我决心写这一篇文章. 虽然网上已经有很多文章珠玉在前,但是我还是想写 ...
- java中的参数传递(只有值传递没有引用传递)
Java中只有传值调用(值传递),没有传址调用(址传递或者引用传递).所以在java方法中改变参数的值是不会改变原变量的值的,但为什么改变引用变量的属性值却可以呢?请看下面的解答. java中的数据类 ...
- java case 多个值_Java switch多值匹配操作详解
这篇文章主要介绍了Java switch多值匹配操作详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 我们都知道 switch 用来走流程分支,大 ...
- for循环与内置方法详解
''' for循环与内置方法详解 ''' # 循环:重复(按照某种规律的)做一件事情# lt = [1, 2, 3, 4] # # ind = 0 # # while True: # print(lt ...
最新文章
- 正则化技巧:标签平滑(Label Smoothing)以及在 PyTorch 中的实现
- Android studio导出的apk在真机上安装提示“文件不存在或已失效”的解决方法
- 强化学习总结(1-2)——model-base(policy evaluation;policy control)
- 计算器的程序代码java_求用JAVA编写的计算器程序代码
- 字符串不替代_【数据挖掘】MySQL中的字符串数据类型
- [LeetCode]--35. Search Insert Position
- android系统广播 定向广播,Android之定向广播
- python标准库os.path中_Python零基础入门学习19:常用标准库之os.path子库
- Ansible@一个高效的配置管理工具--Ansible configure management--翻译(十一)
- 方差分析的SPSS实现
- html模板查询,前台模板查找
- 对比汇新云和猪八戒?
- 计算机的同步操作与异步操作的概念,运城计算机同步与异步的概念和应用方法...
- 最漂亮HTML5高端个人简历自适应模板
- 网易域名邮箱支持POP3/SMTP服务
- MIT公开课: Python 笔记6 二分法,牛顿-拉夫森方法,列表
- aws scp上传下载文件
- 深入理解WebView
- C语言最大公约数和最小公倍数
- 计算机基础讨论,对计算机的基础概念讨论
热门文章
- 中缀试转后缀试及前缀试并计算其结果
- 工作汇报ppt案例_【赠书】开工大吉!今年一定要干过写PPT的!
- (2021) 24 [持久化] 文件系统API
- signature=5bcdc11c0d509d82e0d44c544cfad97b,江苏省职称计算机考试新职称光盘试卷
- java 百度poi_Android应用中使用百度地图API之POI(三)
- vs使用未初始化的内存怎么解决_遇到C语言内存错误怎么办?一定要找准这六个原因...
- 项目一计算机基础知识考核题,2013计算机基础知识试题及答案
- 统计内存使用率shell
- Redis(七):Hash哈希数据类型详解
- iBatis——执行原理