ข้อผิดพลาดของคำสั่ง switch case: การแสดงออกของ case จะต้องเป็น expression ที่คงที่


128

คำสั่ง switch-case ทำงานได้อย่างสมบูรณ์แบบเมื่อวานนี้ แต่เมื่อฉันเรียกใช้โค้ดก่อนหน้านี้คราสเมื่อเช้านี้ทำให้ฉันมีข้อผิดพลาดที่ขีดเส้นใต้คำสั่ง case เป็นสีแดงและพูดว่า: การแสดงออกของ case ต้องแสดงออกอย่างต่อเนื่องมันคงที่ฉันไม่รู้ว่าเกิดอะไรขึ้น นี่คือรหัสของฉันด้านล่าง:

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
คุณอาจถูกลบ / การปรับเปลี่ยนรูปแบบของคุณและรหัสเหล่านั้นไม่ได้อยู่อีกต่อไปหรือสิ่งที่ต้องการ ...
Vicente Plata

โดยRทั่วไปคลาสจะถูกสร้างขึ้นโดยเครื่องมือ IDE / dev ดังนั้นจึงมักจะถูกต้องสำหรับเวอร์ชันของ Android ที่ใช้งานอยู่
cHao

R.id ของฉัน * ใช้ได้ทั้งหมดและมีอยู่ในระดับ gen ของ android .. และยังอยู่ในเค้าโครงหลัก
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จากนั้นเลือก

แทนที่ 'switch' ด้วย 'if'


ฉันเปลี่ยนคำสั่ง switch-case เป็น else-if คำสั่งฉันแค่สงสัยว่าฉันสร้างโครงการ android ใหม่และใช้คำสั่ง switch-case และทำงานได้ดี ..
HeartlessArchangel

1
อาจเป็นไปได้ว่าโครงการแรกของคุณใช้โครงการห้องสมุดและโครงการใหม่ของคุณไม่ได้
Benito Bertoli

ฉันไม่เข้าใจว่าขอโทษฉันจริง ๆ เริ่มต้นที่นี่ .. คุณสามารถอธิบาย
HeartlessArchangel

7
อย่างน้อย eclipse จะช่วยให้คุณแปลงสลับเป็น if / else โดยอัตโนมัติ คลิกที่สวิตช์คำหลัก จากนั้นกด ctrl-1
Darren Cato

1
คอมไพเลอร์ต้องการให้นิพจน์เป็นที่รู้จักในเวลารวบรวม หากไม่มีfinalคีย์เวิร์ดตัวแปรสามารถเปลี่ยนแปลงได้ที่รันไทม์
เบนิโต้ Bertoli

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 ไม่ได้ถูกประกาศให้เป็น int แบบสแตติกสุดท้ายดังนั้นคุณจึงไม่สามารถใช้งานโครงสร้างตัวเรือนสวิตช์ได้ คุณสามารถใช้ถ้าประโยคอื่นแทน


ใช่ฉันได้อ่านแล้วที่ tools.android.com ฉันยังพยายามสร้างโครงการใหม่และใช้รหัสด้านบนและใช้งานได้ดี .. เป็นอย่างไร
HeartlessArchangel

1
tools.android.com/recent/buildchangesinrevision14ดูส่วน "การปรับปรุงโครงการห้องสมุด"
Blackbelt

6
ทำไมพวกเขาถึงทำให้การเปลี่ยนแปลงนี้ไม่มีเหตุผล
Andrew S

8

ทางออกที่ง่ายสำหรับปัญหานี้คือ:

คลิกที่สวิตช์แล้วกดCTL + 1มันจะเปลี่ยนสวิตช์ของคุณเป็นคำสั่งบล็อก if-else และจะแก้ปัญหาของคุณ


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;
    }
}

Enums คงที่ดังนั้นสิ่งนี้จะมีผลกระทบ จำกัด มาก หน้าต่างเดียวที่น่าเป็นห่วงคือการค้นหาสองครั้งที่เกี่ยวข้อง (แรกบน SparseArray ภายในและหลังจากนั้นบนตารางสวิตช์)

ที่กล่าวว่า enum นี้ยังสามารถใช้เพื่อดึงรายการในลักษณะคล่องถ้าจำเป็นโดยการอ้างอิง id ... แต่นั่นเป็นเรื่องราวสำหรับเวลาอื่น


Enums ถูกกีดกันใน 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 เฉพาะดังนั้นมันก็โอเคถ้าฉันใช้ ints อย่างไรก็ตามฉันต้องการทราบตัวอย่างด้วย enum: D
aimiliano

i have specific int types so its ok if i use intsไม่สมเหตุสมผลจริงๆ เกี่ยวกับตัวอย่าง enum: docs.oracle.com/javase/tutorial/java/javaOO/enum.html
nhahtdh

ผมหมายถึงว่าตัวแปรประเภท int เข้ามาในการทำงานจะเป็นหนึ่งในจำนวนนี้ 3 ประเภทดังนั้นมันจะไม่ทำลายขอบคุณอะไรสำหรับตัวอย่าง enum :)
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.