【问题标题】:Can you connect two cases of a switch statement using a comma [duplicate]你能用逗号连接两个 switch 语句吗?
【发布时间】:2021-12-14 20:21:06
【问题描述】:

我一直在我的最新项目中使用 switch 语句,并希望让两个可能的值执行相同的代码。所以我查找了如何做到这一点的方法。我找到的唯一答案是这样的:

switch (element) {
   case hi:
   case hello:
      //do something here
      break;
}

但我做了更多的实验,发现我的 IDE 在我这样做的时候并没有报错:

switch (element) {
   case hi, hello:
      //do something here
      break;
}

所以我尝试了一下,发现它有效。所以我想知道使用这种方法是否有问题,因为我在网上没有找到任何东西。我很想能够使用它,因为它看起来更干净。

【问题讨论】:

标签: java switch-statement


【解决方案1】:

您的原始代码段使用 fall-through 对两种情况给出相同的响应;有些人觉得这很难阅读和理解。 Java 12 为我们提供了两个相关的功能,人们发现它们有助于清理他们的 switch 语句,您可以在此处发现其中之一:

  1. 案例可以用逗号分隔,而不是依赖于直通
  2. 可以使用箭头标签代替冒号和换行符;命令。

因此,如果您发现自己不喜欢 fall-through,并且不想担心是否记住了您的中断命令,您可以将 switch 编写如下:

switch (element) {
    case hi, hello -> // do something here
    case goodbye, bye -> // do something else here
}

请注意,在这种情况下,我们没有任何 break 语句,但在 hi 情况和 bye 情况之间没有失败;由于箭头标签,它们是分开的。

【讨论】:

    【解决方案2】:

    Java 的最新版本(12 及更高版本)已经在 switch 上投入了大量工作。现在有很多形式。其中一些形式的基本原则强烈表明某些新的句法特征很重要,为了保持一致性,如果该特征也可以用于其他形式,那么其他形式也会更新。

    历史

    最初的 java 1.0 开关是 C 的直接副本(这解释了它们完全奇怪和愚蠢的语法;这就是 C 所拥有的,而 java 旨在让 C 编码人员感到舒适。我们可以抱怨这样一个事实,即这意味着语法是愚蠢的,但很难否认 C 风格的语法,不管它看起来多么疯狂,已经占领了这个星球,C、C#、Java 和 Javascript 加在一起占据了“市场”的很大一部分,所以说话)。

    它:

    • 要求您切换的东西在int 上,并且只有int
    • 每个案例都是一个特定且恒定的数字(没有case 10-100,绝对没有case <5case x:)。
    • 它是一个语句(switch 本身没有值,它是一种有条件地跳转到语句的方式)。
    • 与 C 版本不同,将开关的性质视为奇怪的 GOTO 式构造,因此实际上不允许您通过它交错控制结构,例如 do/while 循环(幸运的是,我猜)? - 所以,Duff's Device 在 java 中是不合法的。

    最近更新:

    与枚举一起:开关中的枚举

    Java1.5 带来了枚举,并且由于枚举旨在替换 int 常量,它们需要在开关中可用。鉴于枚举值有一个 int 的“序数”,因此实现很简单:switch (someEnum) { case ENUMVAL: }switch(someEnum.ordinal()) { case 1: } 周围的轻糖,其中 1 是 ENUMVAL 的序数值。

    仅半近期:字符串

    在 JDK7 中,添加了字符串切换支持。相同的原则适用:只有常量,null 是不行的 - 它是“快速”的,因为它实现为一个跳转表(与一系列 if/elseif 语句相反,它需要对每个语句进行比较。一个跳转表只是跳转,使用单个比较,直接跳到右边,如果没有匹配到最后。

    现在的新东西 (12+):作为表达式

    这些天 switch 可以是一个表达式。如,开关返回一个东西。但是,为了使这项工作正常进行,整个 switch 中的每条“路径”都必须返回一些东西,而且不可能是缺少 case 语句的情况(呵呵);毕竟,表达式应该解决什么问题呢?因此,在这种“模式”中,您一定已经用尽了所有选项。有趣的子案例是枚举,您可以在其中“穷举”,但在运行时这永远无法保证;如果有人向枚举添加一个值并重新编译只是枚举并将其放入其中怎么办?现在,以前的详尽(涵盖所有选项)开关不再是:

    int y = switch(textyNumber) {
      case "one": yield 1;
      case "two": yield 2;
      default: yield 0;
    };
    

    yield 是这里的一种新方法。这很像“返回”——它从开关“返回”,返回那个值。如果缺少该默认子句,则会出现编译器错误。

    枚举的奇怪之处在于,如果你穷举(覆盖每个枚举值),它会编译,但如果你添加一个枚举值,不要使用开关重新编译代码,并尝试折腾一个新创建的枚举值通过,开关会抛出一个java.lang.IncompatibleClassChangeError。你知道的越多。

    箭头语法

    因为 'yield' 有点笨拙,而且它可能很有用,只需将所需的表达式单线化,类似于您可以编写的方式,例如:

    Comparator<String> byLength = (a, b) -> a.length() - b.length();
    

    同样的箭头语法现在在 switch 中是合法的,为了保持一致性,它甚至在语句形式的 switch 中也是合法的:

    int x = 1;
    int y = switch(x) {
       case 1 -> 2;
       default -> 0;
    };
    
    switch (y) {
      case 0 -> System.out.println("Interesting");
    }
    

    箭头防止掉线(它暗示break),并且只接受一个语句。但是一整块也算一个语句:

    switch (y) {
      case 0 -> {
        System.out.println("one");
        System.out.println("two");
      }
      case 1 -> {
        System.out.println("three");
      }
    }
    

    只会打印“一”、“二”。

    多案例

    逗号可用于分隔值;这类似于您如何使用条形分隔异常类型(catch (IOException | SQLException e) { ... }。适用于所有表单。

    模式匹配

    现在我们来看看真正有趣的东西:

    record Point(int x, int y) {}
    
    ...
    
    Object p = new Point(10, 20);
    
    switch (p) {
    case Point(x, y) -> System.out.printf("Point [%d, %d]", x, y);
    }
    

    很快就会合法java了!现在,“案例”之后的东西是“模板”。你能把 p 解析到的任何东西粉碎到这个模板中吗?如果是,则大小写匹配,并为您填写变量。这适用于“可解构”类型(目前:仅记录;将来任何类型都可以提供解构函数),以及类似交易的 instanceof:

    Object o = someExpression;
    
    switch (o) {
      case Number n -> System.out.println("is a number. intvalue: " + n.intValue());
      case String s -> System.out.println("is a string: " + s.toLowerCase());
    }
    

    我认为这涵盖了所有可用于切换到 java v 17 甚至更高版本的更新。

    注意:您可以通过关注相应的 openjdk 开发邮件列表,尽可能早地找到此信息。这些东西主要在 amber-dev 上找到,由于与记录密切相关,在 valhalla-dev 上可以找到一些模式匹配的东西,并且记录与值类型重叠(valhalla = java 的值类型,amber = 通用语言更新)。在 Java 会议上,通常有人会详细说明它的位置,reddit 的 /r/java 倾向于在 OpenJDK 团队的某个人(对于这些东西,你通常在看 Brian Goetz)发布有关该功能如何进行的重大更新时发布它设想/已实施。在 Twitter 上关注 Brian,这也有帮助。发行说明以及与任何新的 Java 版本相关的 JEP 总括页面也应该提及这些内容,并带有您可以访问的链接。

    【讨论】:

      【解决方案3】:

      这在 Java 中不可用,但是您可以使用 Kotlin 来做这件事,它与 Java 100% 兼容

      【讨论】:

      • ...它,这就是OP询问的原因。 Java 在这一点上比 kotlin 获得了更多的功能。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-27
      • 2019-05-05
      • 1970-01-01
      • 1970-01-01
      • 2012-04-10
      • 2015-10-13
      相关资源
      最近更新 更多