2014-02-27 1 views
2

왜 다른 방법으로 정의 된 내부 클래스 내부의 최종 변수를 참조 할 수 없습니까?
나는 이것에 관한 주제를 보았고, 대부분의 사람들은 당신의 구성 요소가 최종적이어야한다고 말합니다 .... 그러나 아무도 왜 그런 말을하지 않습니까? !! 나는이 한계 뒤에있는 철학이 무엇인지 모른다.
나를 더 혼란 다음 코드가 잘못이라는 것이다 무엇이 :다른 방법으로 정의 된 내부 클래스 내부의 최종 변수를 참조 할 수없는 이유는 무엇입니까?

JButton removeJBtn = new JButton("Remove"); 
    JButton addJBtn = new JButton("Add"); 
    //... 
    btnNewButton.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      removeJBtn.disable();//Error here,Cannot ... 


     } 
    }); 

나는 (클래스의 몸이 아닌 방법) 멤버 필드로

JButton removeJBtn 

를 정의하는 경우는 아니지만 최종으로 정의해야합니다!


나는이 일상적인 한계에 대한 논리적 인 답변을 정말 고맙게 생각합니다.


적어도 원래의 질문에 대한 참조를 (즉,이 확실히 대답되었습니다!)주세요, 중복으로이 질문을 표시 친애하는 사용자, 내가 그것을 읽어 내 질문에 위에 추가에 대한 링크가 자바가 최종 변수의 가치를 포착하고, 최종 변수의 가치를 포착하고 그 아래의 의견 (16 표)에 의해 완전히 거부되었다고 말하는 사람도있다.

+2

[여기] (http : // stackoverflow.com/questions/1299837/within-an-final-variable-inside-an-different-defined-in-differen를 참조 할 수 없습니다. – Salah

+0

참고 : 내부 클래스와 익명 클래스는 완전히 다른 것입니다! – Smutje

+0

@Smutje : 더 설명해 주시겠습니까? – mok

답변

9

메서드의 로컬 변수는 스택에 있으며 메서드의 수명이 인 경우에만 존재합니다. 로컬 변수의 범위는 변수가 선언 된 메서드로 제한된 이라는 것을 이미 알고 있습니다. 메서드가 끝나면 스택 프레임이 날아가고 변수는 history입니다. 그러나 메서드가 완료된 후에도 예를 들어 참조가 다른 코드로 전달 된 다음 인스턴스 변수에 저장되어 있으면 내부 클래스 개체가 힙에서 계속 작동 할 수 있습니다. 지역 변수는 메서드 로컬의 내부 클래스 객체로 으로 오래 살아있을 수 있으므로, 내부 클래스 객체는이를 사용할 수 없습니다. 로컬 변수가 final로 표시되어 있지 않으면!

소스 : 캐시 시에라 SCJP

+0

그렇다면 removeJBtn이 삭제 된 동안 내부 클래스 (여기의 ActionListener)가 살아있을 수 있다고 말합니까? 그것을 최종으로 표시하는 것은 그것을 계속 유지합니까? – mok

+0

이것은 적절하지 않습니다. 여기에 수락 대답의 코멘트 스레드를 참조하십시오 : http://stackoverflow.com/questions/1299837/cannot-refer-to-a-non-final-variable-inside-an-inner-class-defined-in-a- 차이. 또한 값에 의한 변수 캡처에 대한 좋은 토론은 http://en.wikipedia.org/wiki/Closure_(computer_programming)#Local_classes_.28Java.29에서 확인할 수 있습니다. – Turix

1

일반 변수는 스택 (귀하의 경우 개체에 대한 포인터)에 상주하기 때문에. 내부 클래스는 정의 메소드보다 오래 살 수 있기 때문에 변수는 더 이상 존재하지 않습니다.

변수를 final로 만들면 컴파일러에서 최적화를 만들 수 있습니다 (이 경우에는 최종 변수를 내부 클래스의 "secret"멤버로 포함하십시오.) 변수가 final이 아닌 경우 유효하지 않습니다. 나중에 변경하십시오.

1

다른 답변을 확장하면 익명의 클래스는 구문 클래스 Java 설탕이므로 구체적인 클래스를 작성하지 않고 예를 들어 버튼 리스너를 제공해야 할 때마다 인스턴스화 할 수 있습니다. 원하는 경우 이렇게하면 (익명의 클래스를 쉽게 건너 뛰어 문제없이 구체적인 클래스로 대체 할 수 있습니다.) 내부적으로 사용하기 위해 값 (여기서는 removeJBtn)을 생성자별로 객체에 전달해야하고 새로운 객체를 생성했습니다. tly는 힙에 있기 때문에 청취자를 등록하는 방법보다 길다.