2010-12-29 8 views
11

아래 코드에서 EditText에서 final이라는 키워드를 제거하면 나는 (6) EditText 객체 (et)를 의도에 전달하는 줄에서 오류가 발생합니다. 여기에서 최종 키워드의 중요성을 알고 있어야합니다. ..마지막으로 사용하는 키워드는 무엇입니까?

final EditText et=(EditText)findViewById(R.id.t); 
     Button b=(Button)findViewById(R.id.b1); 
     b.setOnClickListener(new Button.OnClickListener(){ 
      public void onClick(View v)<br> 
      { 
      Intent on=new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+et.getText())); 
      startActivity(on); 
      } 
     }); 
+0

변수 클래스, 메소드 –

+0

그것의 실행 시간이 아닌 컴파일 시간 error.it "다른 방법으로 정의 된 내부 클래스 내부에서 최종 변수가 아닌 것을 참조 할 수 없습니다."이것은 내가 가진 것입니다 ... –

답변

15

여기에서 폐쇄 기능을 사용하고 있기 때문입니다. 즉, 내부 클래스가 인바운드 클래스의 컨텍스트를 사용한다는 의미입니다. 이 변수를 사용하려면 변경되지 않도록 변수를 최종 선언해야합니다.

자세히보기 here

+0

미안 하나를 참조하고 있습니다. 내부 클래스 여기 ... OnClickListener입니까? –

+0

물론 OnClickListener를 구현하는 anonymouse 클래스입니다. –

+0

괜찮아. 고마워. –

2

final은 변수 et을 한 번만 할당하도록 허용합니다. 또한 변수의 범위를 변경하고 onClick visibility 함수를 et에 허용합니다. final이 없으면, et는 onClick 함수 내에서 보이지 않습니다.

+0

어떻게 최종 결재가 onClick에 보이게 할 수 있니? –

20

결승은 근본적으로 변수 et이 어느 시점에서든 재 할당되지 않고 계속 남아 있음을 의미합니다. 이것은 청취자와 같은 내부 클래스가 모든 종류의 문제를 일으킬 수있는 다른 스레드에 의해 재 할당되지 않는다고 믿을 수 있음을 의미합니다.

final은 메소드 또는 클래스 정의를 수정하는 데 사용될 수도 있습니다. 즉, 메소드가 서브 클래스로 대체 될 수 없거나 클래스를 확장 할 수 없음을 의미합니다.

+0

흥미 롭다 나는 그 결말이 그런 효과를내는 방법에 사용될 수 있다는 것을 결코 알지 못했다. 미래의 어떤 시점에서 편리해야합니다. – schwiz

+0

"변수'et'는 재 할당되지 않을 것입니다."가 더 정확합니다. 'final'은 참조 된 객체가 아니라 변수에 적용됩니다. – barjak

0

Here is a linkfinal 키워드에 대해 설명합니다. the specification (섹션 4.12.4)에 따르면 :

변수가 최종 선언 될 수 있습니다. 최종 변수는 한 번만 할당 할 수 있습니다. 할당 직전에 할당되지 않은 변수 (§16)가 아니라면 최종 변수가 할당되면 컴파일 타임 오류가 발생합니다.

3

읽기 this article 관련된 구현 세부 사항을 이해하기 : 우리가 어떻게 구현되는지 로컬 클래스에 대한 몇 가지 빛 창고 경우이 제한 에 대한

이유는 분명해집니다. 익명 로컬 클래스는 로컬 변수를 사용할 수 있습니다. 컴파일러 은 클래스가 사용하는 각 로컬 변수의 복사본을 보유하기 위해 클래스 개인 인스턴스 필드를 자동으로 제공하기 때문입니다. 컴파일러는 각 생성자에 숨겨진 매개 변수를 추가하여 자동으로 생성 된 개인 필드를 초기화합니다. 따라서 로컬 클래스 은 로컬 변수 에 실제로 액세스하지 않고 단지 자신의 개인 복사본에 액세스합니다. 이 경우에만 이 올바르게 작동 할 수있는 유일한 방법은 로컬 변수가 final로 선언되어 있으므로 변수가 변경되지 않는다는 것입니다. 이 보증을 적용하면 로컬 클래스는 변수의 내부 사본 이 실제 로컬 변수를 정확하게 반영한다는 것을 보장합니다.

편집 :

베를린 브라운은 말한다 : "내가 익명의 내부 클래스의 디 컴파일 버전을 기록했다.그러나 솔직히 말해서, 나는 아직도 컴파일러가 그 정보를 가지고 있어야하는 이유를 알지 못합니다. 필드가 final로 선언 된 경우에도 필드는 여전히 null 일 수 있습니다. 내 생각에 이 Java 단점 중 하나라고 생각하면 해당 필드를 선언해야합니다. ... 그게 그 방법입니다. "변수가 아닌 값을 통해 닫습니다"

이유는 사용자가 폐쇄가 실현 있는지 확인하는 것입니다 "왜 명확한 이유가 없습니다. 이제 다음. 최종 로컬 변수를 갖는 요구 사항이 없다고 가정하자 우리가 쓸 수있는 코드와 같은 :

public void doIt() { 
    for(int i = 0; i < 3; ++i) { 
     runnables.add(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println(i); 
      } 
     }); 
    } 
    run(runnables); // run each runnable 
} 

당신은 무엇을 출력 될 것 같아 당신은 실행 가능한이 "변수"를 통해 난을 닫고하지 이후로는 "0 1 2"는 잘못된 것 것 생각한다면? 그 시점에서 i의 "가치"와 출력은 "2 2 2"가 될 것입니다. 여기서 예상되는 행동을 달성하기 위해 할 수있는 일 두 가지 해결책 : 폐쇄가 어떻게 작동하는지 이해하거나 언어 수준에서 어떻게 시행하는지 이해하십시오. 그리고 이것은 언어 디자이너가 따라 갔던 두 번째 옵션입니다.

public void doIt() { 
    for(int i = 0; i < 3; ++i) { 
     final int j = i; // notice the final local variable 
     runnables.add(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println(j); 
      } 
     }); 
    } 
    run(runnables); 
} 

JFTR, 나는 두 번째 옵션 갈 "은"방법이라고 말하는 게 아니에요, 그것은 익명의 내부 클래스에 사용되기 전에 마지막으로 표시된 지역 변수를 가진 것은 나에게 큰 거래 차단기입니다 단지입니다. 물론, YMMV. :-)

+0

익명 내부 클래스의 디 컴파일 된 버전을 게시했습니다. 그러나 솔직히 말해서, 나는 아직도 컴파일러가 그 정보를 가지고 있어야하는 이유를 알지 못한다. 필드가 final로 선언 된 경우에도 필드는 여전히 null 일 수 있습니다. 제 생각에 이것이 자바의 단점 중 하나라고 생각합니다. 마지막 필드를 선언해야합니다. 이유가 명확하지 않습니다. –

+0

@Berlin Brown : 귀하의 우려 사항을 해결하기 위해 답변을 업데이트했습니다. 아직 부족한 부분을 알고 있습니다. –

0

또한 Java가 익명 내부 클래스를 만드는 방법을 이해하는 데 도움이됩니다. 자바가 특정 클래스를 어떻게 구현하는지.

Java는 컴파일러가 컴파일 타임에 해당 객체의 유형을 알아야하기 때문에 해당 변수가 최종적이어야합니다. 그러면 컴파일러는 익명 내부 클래스 구현 (이 경우 'et') 내에 필드를 생성합니다.

형식이 final이 아닌 경우 컴파일러에서 내부 클래스 구현을 작성하는 방법을 결정합니다. 기본적으로 필드를 final로 선언하면 Java 컴파일러에 자세한 정보가 제공됩니다. 컴파일러 도움이되지 않습니다

코드, 익명의 내부 클래스 컴파일되지 않습니다 : 코드 위로

Object et; 
et = a ? new Object() : new EditText(); 

...

을, 자바 컴파일러는 정말를 만들 수 없습니다 익명 내부 클래스.

귀하의 코드 :

최종 글고 치기 등등 = (글고) findViewById를 (R.id.t);

...
new Button.OnClickListener$1(){ 
      public void onClick(View v)<br> 
      { 
      Intent on=new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+et.getText())); 
      startActivity(on); 
      } 
     }); 

... 바이트 코드 클래스, 당신이이 같을 수 있습니다 제공하는 내부 클래스 블록의 구현을 작성합니다 자바 컴파일러.

public class OnClickListener$1 { 

private final EditText et ; <---- this is important 
public OnClickListener$1(final et) { 
    this.et = et; 
} 
public void onClick(View v)<br> 
       { 
       Intent on=new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+et.getText())); 
       startActivity(on); 
       } 
} 

당신은 내가 익명의 바이트 코드 클래스를 $ 1 찾아 그 바이트 코드 파일 디 컴파일 제공하는 의사 코드를 테스트 할 수 있습니다.당신의 로그 캣에 어떤 오류가 발생했습니다었던 당신이 우리를 알 수 있습니다 : 드로이드

Java final variable: If you make any variable as final, you cannot change the value of final variable (It will be constant). 

Java final method: If you make any method as final, you cannot override it. 

Java final class: If you make any class as final, you cannot extend it. 
1

JAVA에서 "최종"키워드의 목적

는 세 가지 수준에서 정의 할 수 있습니까?
관련 문제