is there a workaround for when using a foreach loop to iterate though an arraylist to not make the instance a final?

StackOverflow https://stackoverflow.com/questions/18171894

문제

So when I iterate through my array list of Buttons I'm trying to set all of their onClickedListener()/onFocusChangedListener() but when it comes to modifying of altering the button in the array list it tells me it has to be final.

Code:

        for(Button aBtn : menu_Buttons)
    {
        aBtn.setOnFocusChangeListener(new OnFocusChangeListener(){

            @Override
            public void onFocusChange(View arg0, boolean changed) {
                Log.i("LC", "focus changed");
                if(changed)
                 {
                    aBtn.setTextColor(Color.parseColor("#FFFFFF"));
                     Log.i("LC", "true");
                 }
                 else
                 {
                     aBtn.setTextColor(Color.parseColor("#CD6839"));
                     Log.i("LC", "false");
                 }
            }
        });
    }

SO it asks it to be like this instead.

for(final Button aBtn : menu_Buttons)

Can someone explain this to me, I'm not working at 100% just now and I can't see why it would have to be final.

I have found other ways to iterate through the array list using other methods but this is just bugging me.

도움이 되었습니까?

해결책

Let's step back and look what's going on here:

  1. you have an instance variable (Button aBtn)
  2. you are referencing this instance variable in an inner class (new OnFocusChangeListener(){...})

Now, what's important to remember here is that the inner class's methods will be called at an undefined later date. So the methods contained in it is separate from the current flow of execution. Now imagine the following code:

   for(Button aBtn : menu_Buttons)
{
    aBtn.setOnFocusChangeListener(new OnFocusChangeListener(){

        @Override
        public void onFocusChange(View arg0, boolean changed) {
            Log.i("LC", "focus changed");
            if(changed)
             {
                aBtn.setTextColor(Color.parseColor("#FFFFFF"));
                 Log.i("LC", "true");
             }
             else
             {
                 aBtn.setTextColor(Color.parseColor("#CD6839"));
                 Log.i("LC", "false");
             }
        }
    });

   if(someCondition) {
      aBtn = someOtherButton;
   }
}

In this case aBtn is changed, so which Button instance should the inner class be using when one of its method is called? No matter which one the compiler chooses, it bound to produce ambiguity to the programmer, which in turn would easily become a source of subtle and hard to trace bug.

By forcing final on an instance variable being referenced in an inner class, the compiler removed this ambiguity and makes coding correct programs easier.

다른 팁

The final keyword means that you can't change the value of the variable within its scope. For your loop example, you can think of the variable going out of scope at the bottom of the loop, then coming back into scope with a new value at the top of the loop. Assigning to the variable within the loop won't work.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top