Проблема переключения Java: регистр выражений должен быть константным выражением - PullRequest
26 голосов
/ 20 января 2011

У меня возникла проблема в моем операторе switch / case. Ошибка говорит: «Выражения регистра должны быть константными выражениями». Я понимаю ошибку и могу ее устранить, используя If, но может кто-нибудь сказать мне, почему выражение case должно быть постоянным в switch / case Пример кода моей ошибки:

public boolean onOptionsItemSelected(MenuItem item) {
    int idDirectory = ((MenuItem) findViewById(R.id.createDirectory)).getItemId();
    int idSuppression = ((MenuItem) findViewById(R.id.recycleTrash)).getItemId();
    int idSeeTrash = ((MenuItem) findViewById(R.id.seeTrash)).getItemId();

    switch (item.getItemId()) {
    case idDirectory:
        createDirectory(currentDirectory);
        break;
    case idSuppression:
        recycleTrash();
        break;
    case idSeeTrash:
        seeTrash();
        break;
    }

    return super.onOptionsItemSelected(item);
}

Спасибо за ваше объяснение !!

Ответы [ 3 ]

54 голосов
/ 20 января 2011

Таким образом, его можно оценить на этапе компиляции (статическая проверка)

См .: http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.11 для формального определения switch.

Кроме того, это может помочь вам лучше понять, как switch преобразуется в байт-код:

class Switch {
  void x(int n ) {
    switch( n ) {
      case 1: System.out.println("one"); break;
      case 9: System.out.println("nine"); break;
      default:  System.out.println("nothing"); break;
    }
  }
}

И после компиляции:

C:\>javap -c Switch
Compiled from "Switch.java"
class Switch extends java.lang.Object{
Switch();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

void x(int);
  Code:
   0:   iload_1
   1:   lookupswitch{ //2
                1: 28;
                9: 39;
                default: 50 }
   28:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   31:  ldc     #3; //String one
   33:  invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   36:  goto    58
   39:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   42:  ldc     #5; //String nine
   44:  invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   47:  goto    58
   50:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   53:  ldc     #6; //String nothing
   55:  invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   58:  return

}

См. Эту строку, помеченную как 1:

 1:   lookupswitch{ //2
            1: 28;
            9: 39;
            default: 50 }

Он оценивает значение и переходит к какой-то другой строке. Например, если значение равно 9, оно перейдет к инструкции 39:

   39:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   42:  ldc     #5; //String nine
   44:  invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   47:  goto    58

Который, в свою очередь, переходит к инструкции 58:

   58:  return

Все это было бы невозможно, если бы оно оценивалось динамически. Вот почему.

13 голосов
/ 14 декабря 2011

в Eclipse IDE прост, в переключении предложения CTRL + 1 и преобразовании переключателя предложения - предложение if-else http://tools.android.com/tips/non-constant-fields

3 голосов
/ 20 января 2011

idDirectory и другие должны быть константой, а не объявленной переменной. Switch не будет работать в этом случае, вам нужно переключиться на if-else конструкцию.

РЕДАКТИРОВАТЬ Я понимаю, что имел в виду OP. Именно так работает переключатель на языке Java.

...