사례 문 전환 오류 : 사례 표현식은 상수 표현식이어야합니다.


128

내 스위치 케이스 설명은 어제 완벽하게 작동합니다. 그러나 오늘 아침에 코드를 일찍 실행하면 이클립스에서 빨간색으로 사례 진술에 밑줄을 긋는 오류가 발생했습니다. 아래 내 코드는 다음과 같습니다.

public void onClick(View src)
    {
        switch(src.getId()) {
        case R.id.playbtn:
            checkwificonnection();
            break;

        case R.id.stopbtn:
            Log.d(TAG, "onClick: stopping srvice");
            Playbutton.setImageResource(R.drawable.playbtn1);
            Playbutton.setVisibility(0); //visible
            Stopbutton.setVisibility(4); //invisible
            stopService(new Intent(RakistaRadio.this,myservice.class));
            clearstatusbar();
            timer.cancel();
            Title.setText(" ");
            Artist.setText(" ");
            break;

        case R.id.btnmenu:
            openOptionsMenu();
            break;
        }
    }

모든 R.id.int는 모두 밑줄이 그어져 있습니다.


R.id.playbtn등 의 정의를 제공 할 수 있습니까 ? 모든 것이 정적이고 마지막입니까?
토마스

2
아마 당신은 당신의 레이아웃을 삭제 / 수정했고 그 ID는 더 이상 존재하지 않습니다 ...
Vicente Plata

클래스 R는 일반적으로 IDE / dev 도구로 생성되므로 일반적으로 사용중인 Android 버전에 적합합니다.
cHao

내 R.id. *는 모두 괜찮으며 android ..의 gen 클래스에 있으며 기본 레이아웃에도 있습니다.
HeartlessArchangel

답변:


274

일반 Android 프로젝트에서 리소스 R 클래스의 상수는 다음과 같이 선언됩니다.

public static final int main=0x7f030004;

그러나 ADT 14부터 라이브러리 프로젝트에서 다음과 같이 선언됩니다.

public static int main=0x7f030004;

즉, 상수는 라이브러리 프로젝트에서 최종적이지 않습니다. 따라서 코드가 더 이상 컴파일되지 않습니다.

이에 대한 해결책은 간단합니다. switch 문을 if-else 문으로 변환하십시오.

public void onClick(View src)
{
    int id = src.getId();
    if (id == R.id.playbtn){
        checkwificonnection();
    } else if (id == R.id.stopbtn){
        Log.d(TAG, "onClick: stopping srvice");
        Playbutton.setImageResource(R.drawable.playbtn1);
        Playbutton.setVisibility(0); //visible
        Stopbutton.setVisibility(4); //invisible
        stopService(new Intent(RakistaRadio.this,myservice.class));
        clearstatusbar();
        timer.cancel();
        Title.setText(" ");
        Artist.setText(" ");
    } else if (id == R.id.btnmenu){
        openOptionsMenu();
    }
}

http://tools.android.com/tips/non-constant-fields

다음을 사용하여 switch명령문을 명령문으로 빠르게 변환 할 수 있습니다 if-else.

Eclipse에서
커서를 switch키워드로 이동 하고 Ctrl+를 1누른 다음

'스위치'를 'if-else'로 변환하십시오.

Android Studio에서
커서를 switch키워드로 이동 하고 Alt+를 Enter누른 다음

'스위치'를 'if'로 교체하십시오.


내 switch-case 문을 else-if 문으로 변경합니다. 새로운 Android 프로젝트를 만들고 switch-case 문을 사용하여 제대로 작동하는지 궁금합니다.
HeartlessArchangel

1
첫 번째 프로젝트는 라이브러리 프로젝트를 사용하고 있고 새 프로젝트는 사용하지 않을 수 있습니다.
Benito Bertoli

나는 미안 메신저 정말 초보자 여기 이해가 안
돼요

7
적어도 일식을 사용하면 스위치를 if / else로 자동 변환 할 수 있습니다. 스위치 키워드를 클릭하십시오. 그런 다음 ctrl-1을 누르십시오
Darren Cato

1
컴파일러는 컴파일 타임에 식을 알아야합니다. final키워드가 없으면 런타임시 변수를 변경할 수 있습니다.
베니토 베르톨리

52

프로젝트 속성에서 "Is Library"를 선택 취소하면 나에게 도움이되었습니다.


2
프로젝트 이름을 마우스 오른쪽 버튼으로 클릭하십시오. 그런 다음 속성-> Android를 클릭하십시오. 팝업의 오른쪽 하단에는 "라이브러리"라는 섹션이 있습니다. 그 아래에서 "라이브러리"옵션이 선택되어 있으면 프로젝트를 라이브러리 프로젝트로 사용하지 않으려면 선택 해제하십시오. 그런 다음 청소하고 다시 만드십시오. 라이브러리 프로젝트가 되려면 다른 곳에서 언급 한 것처럼 조건부로 스위치를 변경해야합니다.
VikingGlen

5
라이브러리 프로젝트가 "Is Library"로 표시되는 이유가 있습니다. 이것은 문제에 대한 적절한 해결책이 아닙니다. 일반 앱처럼 작동하는 라이브러리를 만들어서 Android 프로젝트 구조를 손상시킵니다.
ADTC

13

이 방법으로 해결책을 찾을 수 있습니다.

  1. 그냥 지정 정수
  2. 최종 변수 로 만들기

예:

public static final int cameraRequestCode = 999;

이것이 도움이되기를 바랍니다.


8

R.id. *, ADT 14는 더 이상 final static int로 선언되지 않으므로 스위치 케이스 구성에 사용할 수 없습니다. if else 절을 ​​대신 사용할 수 있습니다.


예, tools.android.com에서 읽었으며 위의 코드를 사용하여 새 프로젝트를 만들려고했는데 제대로 작동합니다. 어떻게 작동합니까?
HeartlessArchangel


6
그들이 왜 이런 변화를했는지 이해가되지 않습니다.
Andrew S

8

이 문제에 대한 간단한 해결책은 다음과 같습니다.

스위치를 클릭 한 다음 CTL + 1 을 누르면 스위치가 if-else block 문으로 변경되고 문제가 해결됩니다.


7

if-else 대신 멋진 스위치를 유지하는 다른 솔루션은 어떻습니까?

private enum LayoutElement {
    NONE(-1),
    PLAY_BUTTON(R.id.playbtn),
    STOP_BUTTON(R.id.stopbtn),
    MENU_BUTTON(R.id.btnmenu);

    private static class _ {
        static SparseArray<LayoutElement> elements = new SparseArray<LayoutElement>();
    }

    LayoutElement(int id) {
        _.elements.put(id, this);
    }

    public static LayoutElement from(View view) {
        return _.elements.get(view.getId(), NONE);
    }

}

따라서 코드에서 다음을 수행 할 수 있습니다.

public void onClick(View src) {
    switch(LayoutElement.from(src)) {
    case PLAY_BUTTTON:
        checkwificonnection();
        break;

    case STOP_BUTTON:
        Log.d(TAG, "onClick: stopping srvice");
        Playbutton.setImageResource(R.drawable.playbtn1);
        Playbutton.setVisibility(0); //visible
        Stopbutton.setVisibility(4); //invisible
        stopService(new Intent(RakistaRadio.this,myservice.class));
        clearstatusbar();
        timer.cancel();
        Title.setText(" ");
        Artist.setText(" ");
        break;

    case MENU_BUTTON:
        openOptionsMenu();
        break;
    }
}

열거 형은 정적이므로 영향이 매우 제한적입니다. 우려되는 유일한 창은 관련된 이중 조회 (첫 번째는 내부 SparseArray에서, 나중에 스위치 테이블에서)입니다.

즉,이 열거 형은 필요한 경우 id에 대한 참조를 유지하여 유창한 방식으로 항목을 가져 오는 데 사용할 수 있지만 다른 이야기입니다.


메모리 팽창으로 인해 열거 형은 Android에서 권장하지 않습니다. 이것이 AOSP에서 결코 사용되지 않는 주된 이유이며 어디에서나 ints를 보는 이유입니다.
ADTC


3

클래스에서 선언 된 변수가있는 함수에서 스위치를 사용할 때이 오류가 발생했습니다.

private void ShowCalendar(final Activity context, Point p, int type) 
{
    switch (type) {
        case type_cat:
            break;

        case type_region:
            break;

        case type_city:
            break;

        default:
            //sth
            break;
    }
}

final클래스 시작시 변수를 선언했을 때 문제가 해결되었습니다 .

final int type_cat=1, type_region=2, type_city=3;

1
enum이 경우에 더 나은 대안 int입니다. 메소드의 호출자는 유효하지 않은 유형의 함수를 호출 할 수 없습니다.
nhahtdh

int를 사용하면 특정 int 유형이 있으므로 괜찮습니다. 그러나 나는 열거 형의 예를 알고 싶습니다 : D
aimiliano

i have specific int types so its ok if i use ints실제로 이해가되지 않습니다. 열거 형 예와 관련하여 docs.oracle.com/javase/tutorial/java/javaOO/enum.html
nhahtdh

함수에서 들어오는 int 변수 유형은 항상 이러한 3 가지 유형 중 하나이므로 열거 형 예제 덕분에 아무것도 깨지지 않을 것입니다 :)
aimiliano

i mean that the incoming int variable type in the function will always be one of these 3 types so it won't break anything이것이 당신의 가정입니다. 다른 사람이 임의의 숫자로 함수를 잘못 호출 할 수 있습니다. 를 사용 enum하면 언어에 의해 적용된다고 가정 할 필요가 없습니다.
nhahtdh

2

나는 프로젝트에 라이브러리를 추가하려고 할 때 같은 상황을 겪었다는 것을 언급하고 싶습니다. 갑자기 모든 스위치 문에 오류가 표시되기 시작했습니다!

이제 추가 한 라이브러리를 제거하려고 시도했지만 작동하지 않았습니다. " 프로젝트를 청소할 때 "모든 오류가 발생했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.