Как лучше в java в операторе switch использовать условное (булево) выражение?

Изобрёл такой способ:

boolean pb = false;
switch (pb ? "true" : "false") {
  case "true" -> System.out.println("true");
  case "false" -> System.out.println("false");
  default -> System.out.println("Another");
}

Может есть ещё варианты?

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


Ответы (3 шт):

Автор решения: Roman C

Можно создать enum и пустить его в switch:

enum Bool{TRUE, FALSE};
public class Main {
    public static void main(String[] args) {
      Bool pb = Bool.FALSE;
      switch(pb) {
        case TRUE ->
          System.out.println("true");
        case FALSE -> 
          System.out.println("false");
        default ->
          System.out.println("Another");
      }
    }
}

Если надо, чтобы значения Bool принимали true и false, то его надо переписать следующим образом:

enum Bool{TRUE(true), FALSE(false);
private boolean value;    

  private Bool(boolean value) {
    this.value = value;
  }

  public boolean getValue() {
    return value;
  }
};
→ Ссылка
Автор решения: Nowhere Man

Классический оператор switch НЕ предназначен для обработки аргумента типа boolean/Boolean, для этого вполне достаточно использовать оператор if-else.

Разумеется, можно конвертировать булевскую переменную в какой-то другой тип, допустимый в операторе switch. В соответствии с JLS §14.11 для Java SE 21 такими типами являются char, byte, short, int или ссылочный тип (в т.ч. enum или String).

Примеры допустимых преобразований:

  • целое число при помощи тернарного оператора:
var s = switch (b ? 1 : 0) {
    case 1 -> "ИСТИНА ИСТИННАЯ";
    case 0 -> "ЛЖА ПРЕВЕЛИКАЯ";
    default -> "ЕРЕСЬ НЕВЕДОМАЯ";
};
  • в строку при помощи String.valueOf
var s = switch (String.valueOf(b)) {
    case "true" -> "Jawohl!";
    case "false" -> "Nein!";
    default -> "Unbekannt!";
};
  • В какой-нибудь enum типа того, что указан в ответе Roman C (тогда не понадобится default для switch-выражения):
var s = switch (Bool.of(b)) {
    case TRUE -> "WAHR";
    case FALSE -> "FALSCH";
    case NULL -> "NULL";
};

enum Bool {
    TRUE,
    FALSE,
    NULL;

    public static Bool of(Boolean b) {
        return b == null ? NULL : b ? TRUE : FALSE;
    }
}

В Java 21 ссылочный тип Boolean можно применять в операторе switch, однако соответствующие константы Boolean.FALSE / Boolean.TRUE нельзя использовать напрямую, как значения из enum, поскольку возникнет ошибка pattern or enum constant required:

Boolean pb = true;

switch(pb) {
  case Boolean.TRUE -> System.out.println("TRUE");  // pattern or enum constant required
  case Boolean.FALSE -> System.out.println("FALSE");// pattern or enum constant required
  default -> throw new IllegalArgumentException("Bad value " + pb);
};

То есть, если корректно определить паттерн для сопоставления с типом Boolean, можно получить следующее вполне рабочее решение:

Boolean pb = true;

switch(pb) {
  case null -> System.out.println("NULL");
  case Boolean bb when bb -> System.out.println("TRUE");
  case Boolean bb -> System.out.println("FALSE"); // default не нужен
};

В общем случае в оператор switch может передаваться некая переменная общего типа Object, и потребуется корректно обработать тип boolean при помощи нового механизма:

static void foo(Object o) {
    switch(o) {
        case null -> System.out.println("null");
        case Boolean b when b -> System.out.println("Yes!");
        case Boolean b when !b -> System.out.println("Nope!");
        default -> throw new IllegalArgumentException("bad type of " + b);
    };
}

Фича сопоставления шаблонов (pattern matching) для операторов switch была официально добавлена в Java 21 (см. Java Language Changes for Java SE 21), вышедшей в сентябре 2023 года.

→ Ссылка
Автор решения: Ramiz

Я сам люблю switch, особенно его последние фишки, но это не значит, что его нужно пихать везде где только можно и где нельзя. Не зря он не поддерживает булевые типы. Значит ответ: не возникнет таких ситуаций, не надо прикручивать switch к булевым переменным!

Другое дело когда приходит Object, тогда паттерн мэтчинг нам в помощь.

public static void main(String[] args) {
    Object[] something = {true, false, "true", "false"};
    for (var obj : something) {
        System.out.println(
                switch (obj) {
                    case Boolean b when b -> "bool:true";
                    case Boolean b when !b -> "bool:false";
                    case String s -> "String:" + s;
                    default -> "something";
                });
    }
}
→ Ссылка