10

Почему нельзя использовать оператор switch для строк?

9

Проблема с функциональностью switch в Java

Здравствуйте!

Я хотел бы узнать, планируется ли добавление определённой функциональности в будущем обновлении Java?

Также, не мог бы кто-то объяснить, почему я не могу использовать эту функциональность? Интересно понять, как именно работает оператор switch в Java с технической точки зрения.

Спасибо!

5 ответ(ов)

1

Если в вашем коде есть участок, где вы можете использовать оператор switch с типом String, возможно, стоит рассмотреть возможность рефакторинга строки в перечисление (enum) возможных значений, которое вы сможете использовать в операторе switch. Разумеется, это ограничит потенциальные значения строк только теми, которые перечислены в вашем перечислении, что может быть как плюсом, так и минусом, в зависимости от ваших требований.

Вы также можете добавить в ваше перечисление элемент 'OTHER' и метод fromString(String), после чего ваш код может выглядеть следующим образом:

ValueEnum enumval = ValueEnum.fromString(myString);
switch (enumval) {
   case MILK: lap(); break;
   case WATER: sip(); break;
   case BEER: quaff(); break;
   case OTHER: 
   default: dance(); break;
}

Таким образом, вы получите преимущества строгой типизации и избежите опечаток, связанных со строками.

0

Вот полный пример, основанный на посте JeeBee, где вместо использования пользовательского метода применяются перечисления (enum) в Java.

Обратите внимание, что начиная с Java SE 7, вы можете использовать объект String в выражении оператора switch.

public class Main {

    /**
    * @param args аргументы командной строки
    */
    public static void main(String[] args) {

        String current = args[0];
        Days currentDay = Days.valueOf(current.toUpperCase());

        switch (currentDay) {
            case MONDAY:
            case TUESDAY:
            case WEDNESDAY:
                System.out.println("скучно");
                break;
            case THURSDAY:
                System.out.println("становится лучше");
            case FRIDAY:
            case SATURDAY:
            case SUNDAY:
                System.out.println("гораздо лучше");
                break;

        }
    }

    public enum Days {

        MONDAY,
        TUESDAY,
        WEDNESDAY,
        THURSDAY,
        FRIDAY,
        SATURDAY,
        SUNDAY
    }
}

Этот код принимает в качестве аргумента день недели, сравнивает его с перечислением Days и выводит соответствующее сообщение в зависимости от дня.

0

Ответ на ваш вопрос:

Переключатели на основе целых чисел могут быть оптимизированы до очень эффективного кода. В то время как переключатели, основанные на других типах данных, могут быть скомпилированы только в серию операторов if().

По этой причине языки C и C++ разрешают использовать переключатели только с целочисленными типами, поскольку использование других типов не имело смысла.

Дизайнеры C# решили, что стиль важен, даже если это не дает никаких выгод с точки зрения производительности.

Дизайнеры Java, похоже, придерживались принципов, аналогичных тем, что применялись при разработке C.

0

С начала версии 1.7 в Java стало возможным использовать строковые литералы напрямую в конструкциях switch. Вот пример, который иллюстрирует это:

public static void main(String[] args) {
    
    switch (args[0]) {
        case "Monday":
        case "Tuesday":
        case "Wednesday":
            System.out.println("скучно");
            break;
        case "Thursday":
            System.out.println("становится лучше");
        case "Friday":
        case "Saturday":
        case "Sunday":
            System.out.println("гораздо лучше");
            break;
    }
    
}

В этом примере программа берет первый аргумент командной строки (args[0]) и сравнивает его с днями недели. Если аргумент совпадает с "Monday", "Tuesday" или "Wednesday", программа выводит "скучно". Если же это "Thursday", она сначала выведет "становится лучше", а затем, без использования break, продолжит выполнение для "Friday", "Saturday" и "Sunday", выводя "гораздо лучше". Обратите внимание, что отсутствие break в case "Thursday" означает, что управление перейдет к следующему case.

0

Согласно Джеймсу Каррану, конструкции switch, основанные на целых числах, можно оптимизировать до очень эффективного кода. В то же время конструкции switch на других типах данных могут быть скомпилированы только в серию операторов if(). По этой причине в C и C++ разрешается использовать switch только для целочисленных типов, поскольку использование switch для других типов не имеет смысла.

На мой взгляд, как бы это ни было субъективно, как только вы начинаете использовать switch для не-примитивных типов, возникает необходимость задаться вопросом о различиях между "equals" и "==". Во-первых, сравнение двух строк может быть довольно затратным по времени процессом, что усугубляет проблемы с производительностью, о которых упоминалось ранее. Во-вторых, если вы вводите switch для строк, рано или поздно возникнет потребность в switch, игнорирующем регистр, учитывающим или игнорирующим локаль, основанном на регулярных выражениях и т.д. Я бы поддержал решение, которое сэкономило бы много времени разработчиков языка, пусть и за счет небольших затрат времени для программистов.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь