Как заставить switch case принимать несколько типов данных в Java?

при использовании коммутатора Java он исключает только char и int, но я хочу предоставить строковые случаи. Как сделать это возможным?

6 ответов


у вас не может быть строк в switch-case (пока). он находится на пути в Java 7.

текущие типы, которые он принимает, включают char, byte, short, int, Character, Byte, Short, Integer, или перечислимый тип.

из спецификации языка Java:

тип выражения должен быть char, byte, short, int, Character, Byte, Short, Integer или типом перечисления (§8.9) или ошибкой времени компиляции происходит.

...

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

  • каждое постоянное выражение case, связанное с оператором switch, должно быть назначено (§5.2) типу выражения switch.
  • метка переключателя не имеет значения null.
  • никакие два выражения константы case, связанные с оператором switch, не могут иметь одинаковое значение.
  • At большинство меток по умолчанию могут быть связаны с одним и тем же оператором switch.

как заявили другие ответы, Java (в настоящее время) не поддерживает включение строковых значений. Для достижения одного и того же эффекта обычно используются три подхода:

  • заменить switch цепь if ... else if ... заявления. (Фу.)

  • создайте и заполните хэш-карту, которая отображает строки в целочисленные коды, а затем включите коды.

  • определение enum тип, значения которого имеют имена, которые то же, что и строки, используйте EType.valueOf (String) для сопоставления строк со значениями перечисления и включения значений перечисления. (Это может быть сложнее, если вы обязаны подчиняться правилам стиля идентификатора Java для значений перечисления или если строки содержат символы без идентификаторов.)

  • @Pete Kirkham добавляет "классический Хак" переключения на хэш-код строки. Тем не менее, есть несколько проблем с этим:

    1. это не правильно разберитесь с тем случаем, когда поставляемая строка не является одной из обязательных строк. (Подумайте: многие строки хэшируются в один и тот же хэш-код.)

    2. хэш-коды, скорее всего, будут широко разнесены, поэтому компилятор JIT должен будет скомпилировать коммутатор как последовательность тестов / ветвей на основе значений хэш-кода. Это быстрее, чем тест / ветви на основе String.equals(), но это O(N) ... versus O(1) для коммутатора, который компилируется в прыжок таблица.


что я могу включить?

начиная с Java 6, Вы можете включать только следующие типы:

JLS 14.11 switch сообщении

SwitchStatement:
    switch ( Expression ) SwitchBlock

тип Expression должно быть char, byte, short, int, Character, Byte, Short, Integer или enum type, или происходит ошибка времени компиляции. [...] Каждый case постоянное выражение, связанное с оператором switch, должно быть назначено тип switch Expression.


так что я могу сделать?

в зависимости от вашего варианта использования, вы можете использовать enum вместо String. В отличие от String, вы можете включить enum. Вот пример:

public class EnumSwitchSample {
    static enum Color {
        BLACK, WHITE;
    }
    public static void main(String[] args) {
        test(Color.valueOf("BLACK"));
        // "It's black!"

        test(Color.WHITE);
        // "It's white!"
    }
    static void test(Color c) {
        switch (c) {
            case BLACK:
                System.out.println("It's black!");
                break;
            case WHITE:
                System.out.println("It's white!");
                break;
        }       
    }
}
, enum в Java на самом деле довольно мощный, и вам может даже не понадобиться switch на нем. Вот пример:
public class EnumMemberExample {
    static enum Mood {
        SCREAM("I'M LOUD AND OBNOXIOUS!!!") {
            @Override public String say(String statement) {
                return statement.toUpperCase().replaceAll("!", "!!!");
            }
        },
        WHISPER("Ssh... Be vewy vewy quiet...") {
            @Override public String say(String statement) {
                return statement.toLowerCase().replaceAll("!", "...");
            }
        };          
        final String msg;
        Mood(String msg)    { this.msg = msg; }
        String getMessage() { return msg; }
        abstract String say(String statement);
    }
    public static void main(String[] args) {
        test(Mood.SCREAM);
        // "I'M LOUD AND OBNOXIOUS!!!"
        // "HELLO!!! HOW ARE YOU!!!"

        test(Mood.WHISPER);
        // "Ssh... Be vewy vewy quiet..."
        // "hello... how are you..."
    }
    static void test(Mood m) {
        System.out.println(m.getMessage());
        System.out.println(m.say("Hello! How are you!"));
    }
}

посмотреть также

вопросы


switch-case - это языковая конструкция, предназначенная для приема только интегральных значений. Вы не можете изменить то, как это работает.


Я вы действительно в отчаянии, вы можете включить дайджест строки. Если ты занимаешься такими вещами.

import java.util.zip.Adler32;

public class StringSwitch {

    public static void main(String[] args) {

        String arg;
        if (args == null || args.length == 0) {
            arg = "stackoverflow";
        } else {
            arg = args[0];
        }

        Adler32 algorithm = new Adler32();
        algorithm.update(arg.getBytes());
        int hash = (int) algorithm.getValue();

        switch (hash) {
        case 647693707:
            System.out.println("Programming Q & A");
            break;
        case 145556093:
            System.out.println("Narwhals and bacon");
            break;
        case 193790704:
            System.out.println("How do they work?");
            break;
        }
    }
}

позвольте мне надеть мою догматическую шляпу (и вы кодируете на Java, поэтому я предполагаю, что вы заботитесь об ООП)

вместо того, чтобы спрашивать: как я могу сделать что-то не так? вместо этого спросите: что правильно делать? В этом случае: http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html и для некоторого обсуждения:http://www.c2.com/cgi/wiki?ReplaceConditionalWithPolymorphism