Why do I need to declare a guy inside the "foreach"?

Asked

Viewed 242 times

11

Why in a foreach we always need to declare a variable.

Example:

   for(Pessoa pessoa : pessoas) {
    //qualquer coisa 
   }

In other words, I want to know why it is not possible to do this:

  Pessoa pessoa;
  for(pessoa : pessoas) {
      //qualquer coisa
  }
  • 3
  • @bfavaretto the foreach of c# also works like this, like in java. I just haven’t tested if . NET lets you declare out.

  • 1

    Another interesting link: http://www.guj.com.br/t/for-foreach-ou-iterator-pq/73747/7

  • If it’s GUJ, it’s not interesting :D Just joking... : P Vini Godoy doesn’t usually talk nonsense, at least he should talk less than me :P In C# there is a discussion for the compiler to generate code that avoids O(N2) in foreach nestled. It’s not something simple to do.

  • @bigown do not like much guj, but because of him q referenciei, I have found several posts of him that have clarified many doubts about logic and java.

3 answers

8


The code

ArrayList textos = new ArrayList<String>();
textos.add("texto1");
textos.add("texto2");
for (String t : textos) {
    System.out.println(t);
}

It’s actually compiled like this:

ArrayList textos = new ArrayList<String>();
textos.add("texto1");
textos.add("texto2");
for (Iterator<String> it = textos.iterator(); it.hasNext();) {
    String t = it.next();
    System.out.println(t);
}

If I put the statement out, would it look like? So?

    ArrayList textos = new ArrayList<String>();
    textos.add("texto1");
    textos.add("texto2");
    String t = it.next();
    for (Iterator<String> it = textos.iterator(); it.hasNext();) {
        System.out.println(t);
    }

Try to compile and see if it works.

Can the compiler be smart enough to find a way to solve this? It can. But they would rather not complicate it for little and debatable advantage.

Of course you can do this:

ArrayList textos = new ArrayList<String>();
textos.add("texto1");
textos.add("texto2");
String t;
for (Iterator<String> it = textos.iterator(); it.hasNext();) {
    t = it.next();
    System.out.println(t);
}

I put in the Github for future reference.

It’s simple, isn’t it? Think of a more complex example where the compiler would have to parse other snippets of code to know if it’s all right, if it won’t affect anything performing this operation.

Another important point is that the foreach was created to go from start to end of a data string. It was created to prevent bugs that the programmer could provoke by trying to iterate outside the pattern. Why would you want a specific piece of data - the last one - to escape from the loop? Only the last need could be accessed outside the loop. If you need to do this, better be explicit and put in a variable. It is unlikely that it is worth creating such a complication in the compiler and that it kills one of the advantages of the foreach to solve a case that is rarely used and can always be avoided.

In the end, it was only a decision made. Nothing prevents language from allowing this. It’s just not worth the effort.

6

The simple answer: why specification requires that the value used in for-each be declared in it.

Working out, language designers decided for this model for simplicity - this block works for most cases, and the compiler doesn’t have to worry about the "escaping" variable from the loop. There are several scenarios that do not work with this constraint (accessing the value of the iterated variable after the end of the loop, modifications in the iterator, iteration of multiple variables at the same time / in parallel). But who specified this feature thought that the simplicity of the construction was more important than meeting all scenarios.

3

Just to complement, I’ll put what the @Sorrow said on the link @Diegofelipe posted

 private static void testForEach(ArrayList<String> als) {
  for(String s: als)
    System.out.println(s);
 }

 private static void testIterator(ArrayList<String> als) {
  for(Iterator<String> is = als.iterator(); is.hasNext();) {
   String s = is.next();
   System.out.println(s);
  } 
 }

There he says that both iterations present the same Bytecode and that everything indicates the first option is (or appears to be) only a form of Syntactic Sugar.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.