【问题标题】:Using foreach-loop to construct objects in the array使用foreach-loop构造数组中的对象
【发布时间】:2017-01-12 19:15:02
【问题描述】:

我一直在学习 java,想知道是否可以使用 foreach 循环构造数组内的对象。 使用 for 循环非常简单:

public class Bottle {

    double waterAmount;

    Bottle(){
        waterAmount = 1.0;
    }

    public static void main(String[] args) {

        Bottle[] bottles = new Bottle[3];
        //foreach
        for (Bottle bottle : bottles) {
            bottle = new Bottle();
            System.out.println(bottle.waterAmount);
        }
        //for
        for (int i = 0; i<bottles.length;i++){
            bottles[i] = new Bottle();
            System.out.println(bottles[i].waterAmount);
        }

        System.out.println("index 1: " + bottles[1].waterAmount);
    }
}

当我使用 for 循环运行这个程序时,我得到:

1.0
1.0
1.0
index 1: 1.0

这没关系,因为瓶子阵列已经正确构建。 当我只使用 foreach 执行它时,输出:

1.0
1.0
1.0
Exception in thread "main" java.lang.NullPointerException
    at Bottle.main(Bottle.java:31)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

据我所知,foreach 中的瓶子构造了每个瓶子对象,但它并没有将这些新瓶子分配给数组的每个索引,所以这就是为什么我不能引用瓶子[1].waterAmount。

【问题讨论】:

标签: java arrays for-loop foreach


【解决方案1】:

是的,你可以这样做,但是如果我看到了那个特定的构造,我想知道为什么它是这样做的,而不是仅仅使用传统的 for 循环。

试试:

   Bottle[] bottles = new Bottle[3];
   int counter = 0;

   //foreach
   for (Bottle bottle : bottles) {
        bottles[counter] = new Bottle();
        System.out.println(bottles[counter].waterAmount);
        counter++;
   }

【讨论】:

  • 我认为 foreach 是更好的选择,但我可以看到它会产生一些问题,并且在这种情况下,for 循环的标准非常容易。所以你在这种情况下使用 for 循环?
  • 我会说是的,传统的 for 循环是最好的。我的理由是您想使用计数器作为索引。在我看来,foreach 更适合于集合而不是数组。
  • 虽然此代码有效,但 IMO 可读性不是很好:bottle 变量未使用,可能会生成警告(未使用局部变量 bottle 的值 )。
  • 是的...要正确回答问题,您必须以这种方式编写它,即使它不是很好的代码。在我给出的代码中,bottle 只是用作 foreach 循环的工件来遍历数组的索引。
  • 实际上,您本身并没有创建瓶子......如果您查看数组而不为数组的索引分配值,瓶子每次都是空的。在每次迭代时,Bottle 最终都会成为对 null 的引用。在幕后,您正在分配内存空间,以防瓶子需要指向实际的 Bottle(),但这很简单。
【解决方案2】:

你不能。

实际上你自己在代码中说过:for (Bottle bottle : bottles)。您正在创建一个类型为 Bottle 的新变量 bottle,foreach 将当前迭代分配给该变量。更改局部变量(即使用 new 分配新值)将无效,在原始数组中留下空值。

解决另一个答案:这并不是真正使用 foreach,它只是为了迭代目的而滥用它;一个简单的一会儿也可以。

【讨论】:

  • 问题是,“[是否]可以使用 foreach 循环构造数组内的对象?”答案是肯定的,是的,但它不是“正确的”。答案实际上是使用 foreach,它没有骨头。它编译、运行,达到和传统for循环一样的效果。
  • 字面意思是,语义上不是。如果您留在一个没有 while 和常规 for 循环的世界中,这是一个不错的技巧,但是 1)您正在从循环内部寻址数组,并且 2)您正在使用计数器。这是一个合法的答案,但在任何情况下该解决方案都没有意义。
  • 我知道它的作用,是的,这是一个合法的答案。你所说的一切我在我的回答和它下面的 cmets 中提到。你想在这里达到什么目的?如果您不喜欢这个问题,请对问题投反对票,而不是对解决方案投反对票。
  • 我只是说从 foreach 内部分配变量实际上是不可能的,因为 foreach 的性质。这不是为了它。它使用下面的迭代器和一些黑魔法来寻址数组,它们都不允许更改对 Iterable(或数组)内部对象的引用。当然技巧是可能的,但不适用于例如放。你写的实际上是一个被屏蔽为 foreach 的 while 循环(语义上)。不过,我没有投反对票,只是投了反对票。
猜你喜欢
  • 2014-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多