2014-11-18 3 views
1

정적 메서드를 작성 중이며 내부 메서드에서 변수에 액세스 할 때 문제가 발생합니다. 나는 이클립스에서 다음과 같은 오류를 받고 있어요 :외부 변수가 정의되어 있기 때문에 로컬 변수를 할당 할 수 없습니다.

그것이 바깥 쪽 형식 여기

에 정의되어 있기 때문에 마지막 지역 변수의 RET가 할당 할 수 없습니다

내 코드입니다 :

public static boolean noInternetAlertDialog(Context ctx) { 
    final boolean ret; 

    AlertDialog.Builder builder; 
    builder = new AlertDialog.Builder(ctx); 
    builder.setCancelable(false); 
    builder.setTitle("Error"); 
    builder.setMessage("Connection error"); 

    builder.setPositiveButton("Retry", new DialogInterface.OnClickListener(){ 
     @Override 
     public void onClick(DialogInterface dialog, int which) 
     { 
      dialog.dismiss(); 
      ret = false; 
     } 
    }); 

    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int which) { 
      dialog.dismiss(); 
      ret = false; 
     } 
    });   
    AlertDialog dialog = builder.create(); 
    dialog.show(); 

    if (ret) 
     return true; 
    else 
     return false; 
} 
+0

그냥 선언만으로 시도해보십시오 (즉, final boolean ret = false;) 내부 메소드에 설정하지 마십시오 – Martin

+0

'final = boolean ret;가 아닌'ret = false; '에서이 오류가 발생합니다. ' – smartmouse

+0

번호. 아래 답변을 참조하십시오 – Martin

답변

1

요점은 그 메소드를 포함하는 타입의 로컬 변수가 실제로 익명 클래스의 인스턴스에 복사된다는 것입니다 (이는 활성화 프레임 문제로 인해 발생하지만이 문제와 관련이 없으므로 자세한 내용은 다루지 않습니다). 왜 중첩 된 유형 인스턴스의 변수가 더 이상 동일하지 않습니다. 익명 클래스의 방법이 아닌 최종 변수를 참조 할 수 없기 때문에

void foo() { 
    int a = 3; 
    new Runnable() { 
     @Override 
     public void run() { 
      a += 3; 
     } 
    }; 
} 

이 컴파일되지 않습니다

그래서, 여기에 최초의 예이다. a의 선언에 최종 수정자를 추가하면 a의 값은 사용자가 정의한 익명 클래스의 작성 인스턴스에 복사됩니다. 그러나 a가 선언 된 메소드에는 변경 사항이 표시되지 않으므로 a의 값을 변경할 수 없습니다.

int a = 3; 

    void foo() { 
     new Runnable() { 
      @Override 
      public void run() { 
       a += 3; 
      } 
     }; 
    } 
:

그러나

, 익명 클래스는 둘러싸는 인스턴스의 변수를 수정하는 데 사용할 수있는 그들은 (이 선언되고있는 방법하지 않는 정적)를 둘러싸는 인스턴스에 대한 참조를 가지고, 즉, 정적 없습니다

이 예제는 컴파일되며 anonymous class 인스턴스의 run() 메서드가 호출 될 때마다 a가 3 씩 증가합니다. 이 예제에서는 호출되지 않지만 예제 일뿐입니다. 요약하면, 변수 seatno를 메소드 로컬 변수에서 둘러싸는 유형의 인스턴스 변수로 변환해야합니다. 또는 최종 변수가 한 번만 할당 될 수 있으므로 최종 수정자를 제거해야합니다.

업데이트 : 자바 8에서 효과적으로 최종 변수의 개념 (Java 언어 사양 참조) 도입. 그러나이 게시물의 첫 번째 예에서 변수 a는 여러 번 할당되므로 효과적으로 완료되지 않습니다. 이 예는 여전히 자바 8. (컴파일 에러가 "로컬 변수는 최종 또는 효과적으로 최종이어야합니다 클로징 범위에 정의 된"입니다)

+0

클래스의 시작 부분에 (메서드 앞에)'boolean ret = false; '를 추가하지만 다음과 같은 오류가 발생합니다.'정적 필드가 아닌 정적 참조를 만들 수 없습니다. ' – smartmouse

0

당신은 동기 및 비동기 코드를 혼합하는 컴파일하지 않는다는 것을 의미한다. 부울 메서드는 대화 상자를 표시하기 전에 모든 코드를 실행하고 반환합니다. 대신 콜백을 제공하거나 클릭 리스너 내부에서 메소드를 호출해야합니다. 이런 식으로 뭔가 ... 당신은뿐만 아니라 setPositiveButton()에 대해 동일한 작업을 수행해야합니다

public static void showNoInternetDialog(Context context) { 
//setup here. 
    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int which) { 

      userTappedCancel(); 
     } 
    }); 

} 

private static void userTappedCancel() 
{ 
    //Do whatever you want here 
} 

. 다른 예를 보려면 this 질문을 참조하십시오.

+0

할 수 있습니다. 이 솔루션을 사용하지 않고 "ret"변수의 유효성을 검사하면됩니다. – smartmouse

+0

코드를 사용할 수 없게 만드는 중입니다. 메서드는 모든 코드를 실행하고 사용자가 대화 상자에서 버튼을 탭하기 전에 false를 반환합니다. * 비동기 * 대화 상자를 표시 할 때 값을 얻는 유일한 방법은 클릭 리스너 내부에서 콜백 또는 호출 메소드를 사용하는 것입니다. [Android docs] (http://developer.android.com/guide/topics/ui/dialogs.html)는 대화 상자를 표시하고 사용자 입력에 응답하는 방법을 설명하는 데 아주 능숙합니다. – kevskree

0
public static boolean noInternetAlertDialog(Context ctx) { 
final boolean ret = false; //<+======== this 

AlertDialog.Builder builder; 
builder = new AlertDialog.Builder(ctx); 
builder.setCancelable(false); 
builder.setTitle("Error"); 
builder.setMessage("Connection error"); 

builder.setPositiveButton("Retry", new DialogInterface.OnClickListener(){ 
    @Override 
    public void onClick(DialogInterface dialog, int which) 
    { 
     dialog.dismiss(); 
     // =====> you don't need this - ret = false; 
    } 
}); 

builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 
    @Override 
    public void onClick(DialogInterface dialog, int which) { 
     dialog.dismiss(); 
     // =====> you don't need this - ret = false; 
    } 
});   
AlertDialog dialog = builder.create(); 
dialog.show(); 

if (! ret) return true; else false를 반환합니다. 당신은 단지 false로 설정하기 때문에 }

, 당신은 그것을 변경할 필요가 없습니다.

관련 문제