Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A final counter in a for loop?

Tags:

java

I have this code:

    List<Runnable> r = new ArrayList<>();
    for(int i = 0; i < 10; i++) {
        r.add(new Runnable() {

            @Override
            public void run() {
                System.out.println(i);
            }
        });
    }

It obviously does not compile because i would need to be final to be used in the anonymous class. But I can't make it final because it is not. What would you do? A solution is to duplicate it but I thought there might be a better way:

    List<Runnable> r = new ArrayList<>();
    for(int i = 0; i < 10; i++) {
        final int i_final = i;
        r.add(new Runnable() {

            @Override
            public void run() {
                System.out.println(i_final);
            }
        });
    }

EDIT just to make it clear, I used a Runnable here for the sake of the example, the question is really about anonymous classes, which could be anything else.

like image 360
assylias Avatar asked Mar 13 '12 11:03

assylias


People also ask

What is a counter in a for loop?

In computer programming, a loop counter is a control variable that controls the iterations of a loop (a computer programming language construct).

Can we use Final in for loop?

Adding final keyword makes no performance difference here. It's just needed to be sure it is not reassigned in the loop. To avoid this situation which can lead to confusions.

How do you keep a counter in a for loop Python?

Use the enumerate() function to count in a for loop, e.g. for index, item in enumerate(my_list): . The function takes an iterable and returns an object containing tuples, where the first element is the index, and the second - the item. Copied!

How do you count a loop in Java?

You are printing the total amount of counter every time the loop is executed. So for i=0 that would be counter=1, for i=1 that would be still counter=1, for i=2 the counter increases to 2, for i=3 the counter remains 2 which is printed etc.


1 Answers

I think your solution is the simplest way.

Another option would be to refactor the creation of the inner class into a factory function that does it for you, then your loop itself could be something clean like:

List<Runnable> r = new ArrayList<>();
for(int i = 0; i < 10; i++) {
    r.add(generateRunnablePrinter(i));
}

And the factory function could just declare a final parameter:

private Runnable generateRunnablePrinter(final int value) {
    return new Runnable() {
       public void run() {
           System.out.println(value);
       }
    };
}

I prefer this refactored approach because it keeps the code cleaner, is relatively self descriptive and also hides away all the inner class plumbing.

Random digression: if you consider anonymous inner classes to be equivalent to closures, then generateRunnablePrinter is effectively a higher order function. Who said you can't do functional programming in Java :-)

like image 167
mikera Avatar answered Sep 30 '22 07:09

mikera