Как убедиться, что оператор switch / case имеет все параметры, такие как использование enum? - PullRequest
0 голосов
/ 14 марта 2019

Я хочу создать оператор switch / case в Java и убедиться, что все строки находятся в этом операторе.

Однако в Java легко создать перечисление с простыми строками, т. Е. СЕВЕР, ЮГ, ВОСТОК, ЗАПАД.

Как бы это было сделано для строк с точками и пробелами? т.е. "Это описание", "com.stackoverflow.ClassName"

Ответы [ 2 ]

1 голос
/ 14 марта 2019

Если вы спрашиваете, можете ли вы создать enum, где у констант есть пробелы, тогда ответ будет: " нет ".

Константы перечисления являются обычными идентификаторами Java, такими как имена классов или переменных, поэтому в них не должно быть пробелов или специальных символов.

<Ч />

Однако нельзя ли связать перечисление со строкой? Нет.
Если по какой-либо причине вы хотите, чтобы в вашем случае переключения использовался enum для удобства чтения / краткости, но ваши входные данные Strings, которые могут иметь пробелов , точек , special символы ..., тогда есть способ.

Вам нужно расширить enum, чтобы иметь дополнительное поле (назовем его label ) для хранения этого String.
В вашем методе с регистром коммутации, который использует enum, вы можете вызвать findByLabel метод
который возвращает enum, который соответствует предоставленному String.

Вот небольшой пример класса, который использует ваши enum значения NORTH, EAST, SOUTH, WEST,
связаны с Strings различных (недопустимых имен) структур.

public class EnumExample {

    enum SwitchEnum {
        NORTH   ("North star"),
        EAST    ("Eastpack rulez!"),
        SOUTH   ("https://www.southafrica.net/"),
        WEST    ("java.awt.BorderLayout.WEST");

        private final String label;
        SwitchEnum(final String label) {
            this.label = label;
        }

        @Override
        public String toString() {
            return this.label;
        }

        private static final Map<String,SwitchEnum> map;
        static {
            map = new HashMap<String,SwitchEnum>();
            for (SwitchEnum v : SwitchEnum.values()) {
                map.put(v.label, v);
            }
        }
        public static SwitchEnum findByLabel(String label) {
            return map.get(label);
        }
    }

    public static String doEnumSwitch(String enumString) {
        SwitchEnum enm = SwitchEnum.findByLabel(enumString);
        if (enm != null) {
            String enumReturn = enm.name() +" : "+ enm;
            switch (enm) {
                case NORTH:
                    return enumReturn +" - Up there.";
                case EAST:
                    return enumReturn +" - Now for sale.";
                case SOUTH:
                    return enumReturn +" - Now with 50% more elephants.";
                default:
                    return "UNHANDLED ENUM : "+ enm.name() +" - "+ enm;
            }
        } else {
            return "UNKNOWN ENUM : "+ enumString;
        }
    }

    public static void main(String[] args) {
        System.out.println(doEnumSwitch("North star"));
        System.out.println(doEnumSwitch("Eastpack rulez!"));
        System.out.println(doEnumSwitch("https://www.southafrica.net/"));
        System.out.println(doEnumSwitch("java.awt.BorderLayout.WEST"));
        System.out.println(doEnumSwitch("I only want to get out of here."));
    }
}

Выводит следующее

СЕВЕР: Северная звезда - там наверху.
ВОСТОК: Eastpack рулез! - Сейчас в продаже.
ЮГ: https://www.southafrica.net/ - Теперь на 50% больше слонов.
Необработанный ENUM: WEST - java.awt.BorderLayout.WEST
НЕИЗВЕСТНЫЙ ENUM: Я только хочу выбраться отсюда.

1 голос
/ 14 марта 2019

Я думаю, что главная проблема этого вопроса в том, что ваша IDE сообщает вам, что вы пропускаете значения enum в выражении switch. И спрашивает вас, хотите ли вы добавить их, а не ваш компилятор. Это, конечно, не гарантирует, что пользователь вашего класса enum должен использовать каждое значение.

Есть подход, упомянутый Джошуа Блохом в его книге «Эффективная Java» (глава Emulated extensible enum using an interface), которую можно изменить для работы с переключателем, показанным здесь: Java Enum Switch . Но я думаю, что решение для переключения не не обеспечивает полную безопасность использования всех перечислений.

Но так как вы хотели узнать, существует ли решение с использованием строк, мы также можем попробовать использовать функциональный подход, как показано здесь: Функциональный подход с помощью Enum Switch и заставить его работать со строковыми полями вместо перечислений.

Это может выглядеть следующим образом:

public class Direction {
    private static final String NORTH = "north";
    private static final String SOUTH = "south";
    private static final String EAST = "east";
    private static final String WEST = "west";

    public interface SwitchResult {
        void NORTH();
        void SOUTH();
        void EAST();
        void WEST();
    }

    public static void switchValue(String direction, SwitchResult result){
        switch (direction){
            case NORTH:
                result.NORTH();
                break;
            case SOUTH:
                result.SOUTH();
                break;
            case EAST:
                result.EAST();
                break;
            case WEST:
                result.WEST();
                break;
        }
    }

    public static void main(String[] args) {
        String direction = "west";
        Direction.switchValue(direction, new SwitchResult() {
            @Override public void NORTH() {
                System.out.println("this time north");
            }

            @Override public void SOUTH() {
                System.out.println("this time south");
            }

            @Override public void EAST() {
                System.out.println("this time east");
            }

            @Override public void WEST() {
                System.out.println("this time west");
            }
        });
    }
}

Как вы можете видеть в методе main, если вы хотите вызвать функцию switchValue, вы должны передать вашу строку и реализацию вашего интерфейса, что гарантирует вам возможность переопределить все возможности. В обмен на это код очень избыточен. Этот подход можно использовать, если у вас есть доступ только для чтения к классу, который предлагает набор значений String, и вы хотите построить оператор switch вокруг него. В любом другом месте вы действительно должны придерживаться подхода, использующего перечисления.

Если вы хотите использовать сторонние инструменты, чтобы действительно убедиться в том, что вам не нужно писать какой-либо избыточный шаблонный код, взгляните на:

  1. FindBugs SF_SWITCH_NO_DEFAULT : Но это относится только к ветви по умолчанию оператора switch.
  2. @ EnumMapper : процессор аннотаций, который проверяет во время компиляции, что все константы перечисления обрабатываются
...