Почему «final static int» может использоваться как константа регистра переключателя, а не «final static <your enum>» - PullRequest
20 голосов
/ 09 декабря 2010

Почему этот int-переключатель действителен:


public class Foo {
    private final static int ONE = 1;
    private final static int TWO = 2;

    public static void main(String[] args) {
        int value = 1;
        switch (value) {
            case ONE: break;
            case TWO: break;
        }
    }

}

Пока этот переключатель перечисления не:


import java.lang.annotation.RetentionPolicy;

public class Foo {
    private final static RetentionPolicy RT = RetentionPolicy.RUNTIME;
    private final static RetentionPolicy SRC = RetentionPolicy.SOURCE;

    public static void main(String[] args) {
        RetentionPolicy value = RetentionPolicy.RUNTIME;
        switch (value) {
            case RT: break;
            case SRC: break;
        }
    }

}

Я знаю, что в этом случае должна быть константа, так почему я могу использовать "final static int" в качестве константы, а не "final static "? *

Ответы [ 5 ]

17 голосов
/ 09 декабря 2010

Поскольку метка оператора case должна иметь либо постоянную времени компиляции, либо EnumConstantName. JLS 14.11

Константы времени компиляции могут быть только строками и примитивными типами, как описано в JLS 15.28 . Таким образом, вы не можете использовать static final , так как он не является ни константой времени компиляции, ни именем enum.

8 голосов
/ 09 декабря 2010

Аргумент case должен быть примитивным; это не может быть объект.

Однако вы можете использовать перечисления следующим образом:

RetentionPolicy value = ...
switch (value) {
    case RUNTIME:
    case SOURCE:
}

Поскольку value объявлен как тип RetentionPolicy, вы можете использовать константы enum непосредственно внутри коммутатора.

2 голосов
/ 16 октября 2014

Или просто используйте регистр if-elseif:

private final static int ONE = 1;
private final static int TWO = 2;

public static void main(String[] args) {
    int value = 1;

    if(value.equals(ONE)){

    }
    else if(value.equals(ONE)){

    }

}
1 голос
/ 09 декабря 2010

Компилятор говорит

unqualified enumeration constant name required

Таким образом, ваше значение RT должно быть RUNTIME вместо RetentionPolicy.RUNTIME, чтобы ваш код работал.Но, конечно, это невозможно.Почему бы не использовать перечисление RetentionPolicy напрямую?Если вы хотите придерживаться своего окончательного статического объявления, вам нужно присвоить все перечисление вашей конечной статической переменной.

0 голосов
/ 27 июня 2015

У меня было похожее требование, и я обошел эту проблему, включив порядковый номер Enums вместо включения самого перечисления. Это не очень красиво / интуитивно понятно, но работает:

public class Foo {

    private final static int SRC = 0; // == RetentionPolicy.SOURCE.ordinal();
    private final static int RT = 2; // == RetentionPolicy.RUNTIME.ordinal();

    static{
        if (RT != RetentionPolicy.RUNTIME.ordinal() || SRC !=  RetentionPolicy.SOURCE.ordinal()) {
            throw new IllegalStateException("Incompatible RetentionPolicy.class file");
        }
    }

    public static void main(String[] args) {
        RetentionPolicy value = RetentionPolicy.RUNTIME;
        switch (value.ordinal()) {
            case RT: break;
            case SRC: break;
        }
    }

}

Обратите внимание, что, конечно, невозможно объявить константу, например,

private final static int SRC = RetentionPolicy.SOURCE.ordinal();

по той же причине никто не может объявить константу как Enum в первую очередь ...

...