Подтвердить что ты не робот

Почему "final static int" может использоваться как константа case коммутатора, но не "final static <your enum>",

Почему этот 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" как постоянный, но не "конечный статический < ваш enum > "?

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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)){

    }

}

Ответ 4

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

unqualified enumeration constant name required

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

Ответ 5

У меня было аналогичное требование, и я работал над этой проблемой, включив порядковый номер 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 в первую очередь...