0

I've been learning java and wanted to know if it's possible to construct objects that are inside an array using foreach loop. Using for-loop it's very easy:

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);
    }
}

When I'm running this program using for loop I get:

1.0
1.0
1.0
index 1: 1.0

which is ok because the array of bottles has been constructed properly. When I execute it using only foreach there is the output:

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)

So as much as I understand the bottle inside foreach constructs every bottle object but then it's not asigning those new bottles to the every index of an array so that's why I cannot refer to bottles[1].waterAmount.

9
  • 1
    you will be surprised, but answer is here stackoverflow.com/questions/40480/… Commented Jan 12, 2017 at 19:17
  • 1
    Possible duplicate of What is a NullPointerException, and how do I fix it? Commented Jan 12, 2017 at 19:18
  • 2
    Updating the local variable bottle inside your foreach loop will in no way modify the contents of the array from which that variable was initiatlized. Commented Jan 12, 2017 at 19:18
  • 2
    Related: Why JAVA foreach doesn't change element value? Commented Jan 12, 2017 at 19:19
  • @azurefrog that's exactly what I'm asking about. So is there any way to use foreach loop to work like for loop in the case? Commented Jan 12, 2017 at 19:19

2 Answers 2

2

Yes, you can do it, but if I saw that particular construct I'd want to know why it was done that way instead of just using the traditional for loop.

Try:

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

   //foreach
   for (Bottle bottle : bottles) {
        bottles[counter] = new Bottle();
        System.out.println(bottles[counter].waterAmount);
        counter++;
   }
Sign up to request clarification or add additional context in comments.

6 Comments

I thought that foreach is better option but as I can see it can create some problems and standard for loop is super easy in this case. So you to use for loop in this case?
I'd say yes, the traditional for loop is the best. My reasoning is that you wanted to make use of a counter as an index. foreach, in my opinion, is more suited to collections than it is to arrays.
Although this code works, IMO it's not very readable: the bottle variable is not used and may generate a warning (The value of the local variable bottle is not used).
Yup... To answer the question properly you have to write it this way even though it's not really good code. In the code I gave, bottle is just used as an artifact of the foreach loop to iterate through the indexes of the array.
Actually, you're not creating bottle per se... if you look at the array without assigning values to the indexes of the array, bottle is null every time. Bottle ends up being a reference to null upon each iteration. Behind the scenes you are allocating memory space in case bottle needs to point to an actual Bottle(), but that's trivial.
|
1

You can't.

Actually you said it yourself in your code: for (Bottle bottle : bottles). You're creating a new variable, bottle, of type Bottle, to which foreach assigns current iteration. Changing the local variable (i.e. assigning new value using new) will have no effect, leaving you nulls in original array.

To address the other answer: that's not really using foreach, it's merely abusing it for iteration purposes; a simple while would have worked as well.

4 Comments

Question was, "[is it] possible to construct objects that are inside an array using foreach loop?" The answer is yes, it is, but it isn't "proper." The answer IS actually using a foreach, there's no bones about it. It compiles, runs, and achieves the same effect as the traditional for loop.
Literally yes, semantically not really. It's a nice trick if you're left in a world without while and regular for loop, but 1) you're addressing the array from inside the loop and 2) you're using a counter. It's a legit answer, but there isn't a situation where that solution would make sense.
I know what it does, and yes, it is a legit answer. Everything that you said I mentioned in my answer and in the comments below it. What are you trying to achieve here? If you don't like the question, downvote the question, not the solution.
I'm just stating that assigning variable from inside foreach isn't really possible due to the nature of foreach. It's not meant for it. It uses Iterators underneath and some black magic to address arrays, neither of which allows changing references to objects inside Iterable (or the array) Sure tricks are possible, but not applicable on e.g. set. What you wrote is actually a while loop (semantically) masked as foreach. I didn't downvote anything though, just got downvoted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.