【问题标题】:How to make switch case accept multiple data types in Java?java - 如何使switch case接受Java中的多种数据类型?
【发布时间】:2011-02-28 13:49:03
【问题描述】:

在使用 Java 的 switch case 时,它​​除了 char 和 int,但我想提供 string case。如何让这成为可能?

【问题讨论】:

    标签: java language-features switch-statement


    【解决方案1】:

    您不能在 switch-case 中使用字符串(目前)。 It's on its way in Java 7.

    它当前接受的类型包括charbyteshortintCharacterByteShortInteger或枚举类型。

    来自 Java 语言规范:

    表达式的类型必须是 char、byte、short、int、Character、Byte、Short、Integer 或枚举类型(第 8.9 节),否则会发生编译时错误。

    ...

    以下所有条件都必须为真,否则会导致编译时错误:

    • 与 switch 语句关联的每个 case 常量表达式都必须可分配(第 5.2 节)到 switch 表达式的类型。
    • 没有开关标签为空。
    • 与 switch 语句关联的两个 case 常量表达式不能具有相同的值。
    • 最多可以有一个默认标签与同一个 switch 语句相关联。

    【讨论】:

      【解决方案2】:

      正如其他回复所述,Java(当前)不支持打开字符串值。实现相同效果的常用方法有以下三种:

      • switch 替换为if ... else if ... 语句链。 (呸)。

      • 创建并填充将字符串映射到整数代码的 HashMap,然后打开代码。

      • 定义一个 enum 类型,其值的名称与字符串相同,使用 EType.valueOf(String) 将字符串映射到枚举值,然后打开枚举值。 (如果您需要遵守枚举值的 Java 标识符样式规则,或者如果字符串包含非标识符字符,则可能会更复杂。)

      • @Pete Kirkham 添加了打开字符串哈希码的“经典技巧”。但是,这样做有几个问题:

        1. 它不能正确处理提供的字符串不是所需字符串之一的情况。 (想一想:许多字符串哈希到相同的哈希码。)

        2. 哈希码很可能间隔很宽,因此 JIT 编译器必须根据哈希码值将开关编译为一系列测试/分支。这比基于String.equals() 的测试/分支要快,但它是O(N) ... 与O(1) 相比,用于编译为跳转表的开关。

      【讨论】:

      • 您忘记了打开字符串哈希码的经典技巧。
      • switch 语句不会编译成哈希映射或类似的东西吗?
      • 就我个人而言,我从来没有考虑过 if/elseif 链以任何方式“糟糕”。
      • @pxl - 不这么认为。如果我没记错的话,开关的电平非常低......基本上相当于goto。是的,刚刚检查过......这是一个花哨的 goto。我很确定我见过有人用开关做疯狂的事情(比如疯狂炫耀)。
      • @CurtainDog - JIT 编译器将生成一个分支表或一系列测试和分支,具体取决于(整体)标签值的密度。
      【解决方案3】:

      我可以打开什么?

      从 Java 6 开始,您只能开启以下类型:

      JLS 14.11 The switch statement

      SwitchStatement:
          switch ( Expression ) SwitchBlock
      

      Expression 的类型必须是 charbyteshortintCharacterByteShortInteger 或 @9876543 类型,或发生编译时错误。 [...] 与 switch 语句关联的每个 case 常量表达式必须可分配给 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;
              }       
          }
      }
      

      然而,Java 中的enum 实际上是相当强大的,你甚至可能不需要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!"));
          }
      }
      

      另见

      相关问题

      【讨论】:

        【解决方案4】:

        switch-case 是一种语言结构,旨在仅接受整数值。你不能改变它的工作方式。

        【讨论】:

        • 不幸的是,真的。以其他语言工作。
        • @Mark - 一些 其他语言。我可以列出一些它没有的语言!
        • @Mark 适用于 javascript、actionscript 等,不适用于 C、Java - 可以肯定地说区别是编译还是脚本?
        • 也可以在 C# 中使用。也许区别在于 ECMA。
        【解决方案5】:

        我真的很绝望,你可以打开字符串的摘要。如果你喜欢这样的事情。

        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;
                }
            }
        }
        

        【讨论】:

          【解决方案6】:

          让我戴上教条式的帽子(你正在用 Java 编码,所以我假设你关心 OOP)

          而不是问:我怎么做错了?而是问:什么是正确的做法?在这种情况下:http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html 并进行一些讨论:http://www.c2.com/cgi/wiki?ReplaceConditionalWithPolymorphism

          【讨论】:

            猜你喜欢
            • 2013-10-27
            • 1970-01-01
            • 2020-08-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-06-11
            相关资源
            最近更新 更多