使用 Java foreach 遇到的问题

本文通过实例对比了使用foreach与for循环修改数组元素的效果,揭示了foreach无法直接修改数组元素的原因,并提供了正确的实现方式。

本来以为使用foreach就和使用for循环是一样的效果,结果,却遇到了意料之外的事情。

先来看一个例子:

    public void testArray() {
        //定义一个一维数组 
        int arr[] = {1,3,2,4}; 
        System.out.println("----输出刚刚定义的数组----"); 
        for (int x : arr) {             
            System.out.println(x);          
        } 

        //通过索引给数组元素赋值 
        System.out.println("----通过foreach循环修改数组元素的值----"); 
        for (int x : arr) { 
            x *= 2;
            System.out.println(x);          
        } 

        //循环输出创建的数组 
        System.out.println("----修改后,foreach重新输出数组元素的值----"); 
        for (int x : arr) { 
            System.out.println(x); 
        }        
    }

运行出来的结果:

----输出刚刚定义的数组----
1
3
2
4
----通过foreach循环修改数组元素的值----
2
6
4
8
----修改后,foreach重新输出数组元素的值----
1
3
2
4

咦,怎么没有修改过来?

网上查找答案,这个说得比较明白:

https://www.zhihu.com/question/36905481

给你举一个例子,你看一下可能比较能理解:

for(int element:array1){//question:为什么用Foreach无法给数组赋值。
   element =  r.nextInt(101)+1;
   System.out.println(element);

}//虽然可以输出十个随机数,但并没有把十个随机数赋给array1数组。

这其中的执行过程是这样的
element = array1[i]
element = 随机数
syso(element)
element是个基本数据类型,他不指向数组元素的地址,他只代表数字他自己。

当理解了这个例子,你现在就应该知道foreach这东西的限制了。那就是不能修改数组元素,为什么呢?因为每一次loop你只是获得了当前元素的值,却没有获得当前元素在数组中的对象句柄。这样你就无法直接操作对应的句柄。

所以当你想遍历数组并只想获得元素值的时候才用foreach。其他的时候比如想修改数组,或者想获得index的时候就别用foreach。

现在,我们是想修改数组的值,那么就不能使用foreach了,还是使用for循环吧:

    public void testArray1() {
        //定义一个一维数组 
        int arr[] = {1,3,2,4}; 
        System.out.println("----输出刚刚定义的数组----"); 
        for (int x : arr) {             
            System.out.println(x);          
        } 

        //通过索引给数组元素赋值 
        System.out.println("----通过循环变量给数组元素赋值----");        
        for (int i = 0; i < arr.length; i++) { 
            arr[i] *= 2; 
            System.out.println(arr[i]);         
        } 

        //循环输出创建的数组 
        System.out.println("----修改后,foreach重新输出数组元素的值----"); 
        for (int x : arr) { 
            System.out.println(x); 
        }        
    }

运行结果如下:

----输出刚刚定义的数组----
1
3
2
4
----通过循环变量给数组元素赋值----
2
6
4
8
----修改后,foreach重新输出数组元素的值----
2
6
4
8

长吁一口气,终于恢复正常了。

参考:
http://www.cnblogs.com/hnrainll/archive/2011/11/13/2247422.html
https://www.zhihu.com/question/36905481

Java 中,`foreach` 循环(也称为增强型 `for` 循环)的设计目的是简化对数组或集合的遍历操作。然而,如果尝试在 `foreach` 循环中修改外部的 `long` 类型变量,可能会遇到一些限制或问题,具体表现如下: ### `foreach` 循环中修改外部 `long` 变量问题 Java 的 `foreach` 循环本质上是一个语法糖,它在底层通过 `Iterator` 实现对集合的遍历。由于 `foreach` 循环的设计仅允许遍历和读取集合中的元素,而不支持对集合进行结构性修改(如添加或删除元素),因此在尝试使用外部变量(如 `long` 类型变量)时,可能会因为作用域或不可变性而受到限制。 如果尝试在 `foreach` 循环中修改外部的 `long` 变量,需要注意以下几点: - `long` 是基本数据类型,其变量Java 中是按值传递的,因此在 `foreach` 循环体内对 `long` 变量的修改不会影响到循环外部的值。 - 如果需要在遍历过程中对 `long` 类型变量进行累积操作(如求和、计数等),可以通过在循环体内直接操作变量实现,例如: ```java long total = 0; for (Integer value : numbers) { total += value; } ``` 在上述代码中,`total` 是一个外部的 `long` 类型变量,虽然它在 `foreach` 循环中被修改,但这种修改是允许的,因为它不涉及对集合的结构性修改[^1]。 ### 多线程环境下的注意事项 如果在多线程环境下使用 `foreach` 循环,并且多个线程同时修改外部的 `long` 类型变量,需要考虑线程安全性。由于 `long` 类型的变量操作在 Java 中不是原子性的(特别是在 32 位 JVM 上),因此需要通过同步机制来确保线程安全。例如,可以使用 `synchronized` 关键字或 `AtomicLong` 类来实现线程安全的操作: ```java import java.util.concurrent.atomic.AtomicLong; AtomicLong total = new AtomicLong(0); for (Integer value : numbers) { total.addAndGet(value); } ``` 在此示例中,`AtomicLong` 提供了原子操作,确保了在多线程环境下对 `total` 变量的修改是线程安全的[^2]。 ### `foreach` 循环的替代方案 如果需要在遍历集合时对集合进行结构性修改(如删除元素),应使用 `Iterator` 替代 `foreach` 循环。`Iterator` 允许在遍历过程中安全地删除元素,例如: ```java Iterator<Integer> iterator = numbers.iterator(); while (iterator.hasNext()) { Integer value = iterator.next(); if (value < 10) { iterator.remove(); } } ``` 在此示例中,`iterator.remove()` 方法可以在遍历过程中安全地删除元素,而不会引发 `ConcurrentModificationException` 异常[^1]。 ### 示例代码 以下是一个完整的示例,演示如何在 `foreach` 循环中使用外部的 `long` 类型变量进行求和操作: ```java import java.util.Arrays; import java.util.List; public class ForeachLoopExample { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); long total = 0; for (Integer value : numbers) { total += value; } System.out.println("Total: " + total); } } ``` 在上述代码中,`total` 是一个外部的 `long` 类型变量,它在 `foreach` 循环中被修改,并最终输出求和结果。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值