지역변수에 final이 붙을 때의 의미에 대해


만일 아래 코드에서 mText에 final이 붙지 않은 상태에서  

layout.setOnTouchListener()에서 mText를 사용하고자 하면

컴파일 단계에서 아래와 같은 에러가 발생한다.


Cannot refer to a non-final variable mText inside an inner class defined in a different method


이유가 뭘까? 같은 onCreate() 메소드 안에 있는 변수인데...?

그 이유는...


public class AAAActivity extends Activity  {

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        

        final TextView mText = (TextView)findViewById(R.id.textV);

        

        LinearLayout layout = (LinearLayout)findViewById(R.id.linear);

        layout.setOnTouchListener(new View.OnTouchListener() {

          public boolean onTouch(View v, MotionEvent e) {

              mText.setText("Touched"); //에러 발생

                return true;

          }

        });

    }


  • mText는 전역변수도 아니고, onTouch()의 지역 변수도 아니며 onCreate()의 지역 변수로 선언되어 있다.
  • 리스너인 onTouch()는 onCreate()에 속한 지역 메서드가 아니라는 점을 주의해야 한다. onCreate()가 실행시에 onTouch()가 같이 실행되는 것이 아니라 터치 이벤트 발생시 실행할 메스드로 등록만 할 뿐이다.
  • 에러가 발생하는 이유는 mText 변수는 onCreate()가 리턴되면 사라지는 지역 변수이다.  반면 onTouch()는 터치 리스너로 등록되며 onCreate()가  리턴된 후에라도 이벤트가 발생하면 언제든지 호출될 수 있다. onTouch()가 호출되었을 때는 mText 변수가 존재하지 않으므로 mText의 실제값을 참조할 길이 없다. 미래에 호출될 리스너에게 현재의 지역 변수값을 전달하는 것은 불가능하다.
  • 그런데 여기서 지역 변수에 final을 붙이면 더 이상 변경할 수 없는 상수가 되므로 onTouch()를 등록하는 시점에 그 값을 분명히 전달할 수 있다. 



+ Recent posts