0

I am a beginner with both java and android. In an app I was trying to make, I was using the following for loop:

for(int current = 0; current < cityDetailsArray.size(); current++) {
            row = new TableRow(this);

            OnClickListener rowClickListener = new OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    showDetailsView(cityDetailsArray.get(current)); //error - Cannot refer to a non-final variable current inside an inner class defined in a different method
                }
            };

            row.setOnClickListener(rowClickListener);
                    //rest of the loop
}

So as shown in the comment an error popped up, the fix was to add final to the int current. I did just that and then this error popped up in the final int current line:

The final local variable current cannot be assigned. It must be blank and not using a compound assignment

For which the fix is not shown, but obviously it is to remove the final. What can I do to resolve this?

Harikrishnan
  • 7,765
  • 13
  • 62
  • 113

4 Answers4

4

The only option you have is to declare another variable inside the for loop:

for(int current = 0; current < cityDetailsArray.size(); current++) {
            row = new TableRow(this);
            final int currentCopy = current;

            OnClickListener rowClickListener = new OnClickListener() {

                @Override
                public void onClick(View v) {
                    showDetailsView(cityDetailsArray.get(currentCopy)); 
                }
            };

            row.setOnClickListener(rowClickListener);
                    //rest of the loop
}

You of course cannot make the loop variable current final, as you are incrementing it in the increment/decrement section of the loop itself. Also, you can't use a non-final local variable inside an anonymous inner class. You could have made current an instance variable, but that is hardly an acceptable way.

So, to use current inside the anonymous class, you can create the copy of that variable, and make currentCopy final. So for each iteration of the loop, you'll create a new variable having the same value as current, and that will serve your purpose.

Community
  • 1
  • 1
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • 4
    @HarikrishnanT do not only try to *solve* the problem. It would be better if you understand the problem and why this proposed solution worked. – Luiggi Mendoza Apr 15 '14 at 05:50
  • I understood how it worked, but there is a doubt, if this is the only way, each time we get in the for loop it is creating a new variable, it will be memory consuming na? – Harikrishnan Apr 15 '14 at 05:56
  • @HarikrishnanT That would hardly be an issue. The variable will go out of scope after each iteration. So you can expect the memory to be cleaned up when needed by GC. – Rohit Jain Apr 15 '14 at 05:57
  • 2
    @HarikrishnanT posted another answer where you don't need that `int current` at all, and the code is more readable and easier to handle. – Luiggi Mendoza Apr 15 '14 at 06:00
4

A better option would be using enhanced for loop, so you won't need the final int variable nor the int variable:

for (final CityDetail cityDetail : cityDetailsArray) {
    OnClickListener rowClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            showDetailsView(cityDetail);
        }
    };
    row.setOnClickListener(rowClickListener);
    //rest of the loop
}

Note that when passing data from the current method to an anonymous class you need to use a final variable since the anonymous inner class should not be able to modify the reference (on in case of a primitive, it's value).

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
0

You could create a final field in your listener and assign it the value of current.

Kevin Krumwiede
  • 9,868
  • 4
  • 34
  • 82
-1

declare current variable as global..

int current = 0; // declare global..

and do like this..

for(; current < cityDetailsArray.size(); current++) { row = new TableRow(this);

        OnClickListener rowClickListener = new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                showDetailsView(cityDetailsArray.get(current)); //error - Cannot refer to a non-final variable current inside an inner class defined in a different method
            }
        };

        row.setOnClickListener(rowClickListener);
                //rest of the loop

}

  • -1: even if you declare it above for loop. you won't be able to access it in inner class. As it should be final, so making it global will not solve the problem. – sakura Apr 15 '14 at 07:09