此功能是否将在以后的Java版本中使用?
有人可以解释为什么我不能这样做吗,就像Java switch语句的技术方法那样?
"Don't hold your breath."哈哈,bugs.sun.com
                此功能是否将在以后的Java版本中使用?
有人可以解释为什么我不能这样做吗,就像Java switch语句的技术方法那样?
"Don't hold your breath."哈哈,bugs.sun.com
                Answers:
带有String案例的switch语句已在Java SE 7中实现,至少在首次提出要求后的 16年。没有提供延迟的明确原因,但可能与性能有关。
现在,该功能已javac 通过“脱糖”过程实现。String在case声明时使用常量的干净,高级语法在编译时扩展为遵循模式的更复杂的代码。生成的代码使用始终存在的JVM指令。
switch带有Stringcase的A 在编译期间转换为两个开关。第一个将每个字符串映射到一个唯一的整数-它在原始开关中的位置。这是通过首先打开标签的哈希码来完成的。相应的情况是if测试字符串是否相等的语句;如果哈希上有冲突,则测试为级联if-else-if。第二个开关在原始源代码中进行镜像,但是用相应的位置替换了大小写标签。此两步过程使保留原始交换机的流量控制变得容易。
有关的更多技术深度switch,请参考JVM规范,其中描述了switch语句的编译。简而言之,有两种不同的JVM指令可用于切换,具体取决于案例使用的常量的稀疏性。两者都依赖于每种情况下使用整数常量来有效执行。
如果常量密集,则将它们用作指令指针表(指令)的索引(减去最小值后)tableswitch。
如果常量稀疏,则对lookupswitch指令的正确大小写进行二进制搜索。
在switch对String物体进行除糖时,可能会同时使用这两种指令。在lookupswitch对散列码的第一开关以找到的情况下的原始位置是合适的。由此产生的序数是自然适合tableswitch。
两条指令都要求在编译时对分配给每种情况的整数常量进行排序。在运行时,虽然O(1)性能tableswitch一般显得比更好O(log(n))的性能lookupswitch,它需要一些分析,以确定该表是否是密集足以证明时空权衡。Bill Venners写了一篇很棒的文章,其中更详细地介绍了此内容,同时还深入介绍了其他Java流程控制指令。
在JDK 7之前,enum可以近似String基于的开关。这将使用编译器针对每种类型生成的静态valueOf方法enum。例如:
Pill p = Pill.valueOf(str);
switch(p) {
  case RED:  pop();  break;
  case BLUE: push(); break;
}Pill基于某种方式采取行动,str我认为if-else是更可取的,因为它允许您处理strRED,BLUE范围之外的值,而无需捕获异常valueOf或手动检查与名称的匹配每个枚举类型只会增加不必要的开销。以我的经验,只有在valueOf以后需要String值的类型安全表示形式时,才可以使用将其转换为枚举。
                    (hash >> x) & ((1<<y)-1)对于每个hashCode不同的字符串,其值集将产生不同的值,并且(1<<y)少于字符串数的两倍(或等于)至少不超过该值)。
                    如果您在代码中有一个可以打开String的位置,那么最好将String重构为可能值的枚举,然后可以将其打开。当然,您可以将可能具有的字符串的潜在值限制为枚举中的那些值,这可能会或可能不会。
当然,您的枚举可以包含“ 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;
}以下是基于JeeBee的帖子的完整示例,使用Java枚举而不是自定义方法。
请注意,在Java SE 7和更高版本中,可以在switch语句的表达式中使用String对象。
public class Main {
    /**
    * @param args the command line arguments
    */
    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("boring");
              break;
          case THURSDAY:
              System.out.println("getting better");
          case FRIDAY:
          case SATURDAY:
          case SUNDAY:
              System.out.println("much better");
              break;
      }
  }
  public enum Days {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
  }
}基于整数的开关可以优化为高效代码。基于其他数据类型的开关只能编译为一系列if()语句。
因此,C&C ++仅允许在整数类型上进行切换,因为它与其他类型无关。
C#的设计师认为即使没有优势,样式也很重要。
Java的设计师显然像C的设计师那样思考。
String从1.7开始的直接用法示例也可能显示:
public static void main(String[] args) {
    switch (args[0]) {
        case "Monday":
        case "Tuesday":
        case "Wednesday":
            System.out.println("boring");
            break;
        case "Thursday":
            System.out.println("getting better");
        case "Friday":
        case "Saturday":
        case "Sunday":
            System.out.println("much better");
            break;
    }
}James Curran简洁地说:“可以将基于整数的开关优化为非常有效的代码。基于其他数据类型的开关只能编译为一系列if()语句。因此,C&C ++仅允许对整数类型进行开关,因为它与其他类型毫无意义。”
我的观点(仅此而已)是,一旦您开始启用非基本体,就需要开始考虑“等于”与“ ==”。首先,比较两个字符串可能是一个相当漫长的过程,从而增加了上面提到的性能问题。其次,如果需要打开字符串,则需要忽略大小写的字符串,考虑/忽略语言环境的字符串,基于正则表达式的字符串....我赞成这样的决定,该决定可以节省很多时间:语言开发人员会以少量的时间为程序员付出代价。
matched而not matched。(不过,没有考虑到[named] groups / etc之类的东西。)
                    除了上述良好的论据外,我switch还要补充指出的是,今天很多人都将其视为Java程序过时的一部分(回溯至C时代)。
我并不完全同意这种观点,我认为switch在某些情况下可以发挥它的作用,至少是因为它的速度,无论如何,它比else if我在某些代码中看到的一系列级联数字更好。
但是确实,值得一看的是您需要一个开关的情况,看看是否不能用更多的OO代替它。例如Java 1.5+中的枚举,也许是HashTable或其他一些集合(有时我很遗憾,我们没有作为一流公民的(匿名)函数,如Lua(没有开关)或JavaScript)或什至是多态。
如果您没有使用JDK7或更高版本,则可以使用hashCode()它进行仿真。因为String.hashCode()通常为不同的字符串返回不同的值,并且对于相等的字符串总是返回相等的值,所以它是相当可靠的(不同的字符串可以产生与注释中提到的@Lii相同的哈希码,例如"FB"和"Ea"),请参见documentation。
因此,代码如下所示:
String s = "<Your String>";
switch(s.hashCode()) {
case "Hello".hashCode(): break;
case "Goodbye".hashCode(): break;
}这样一来,您就可以从技术上打开int。
另外,您可以使用以下代码:
public final class Switch<T> {
    private final HashMap<T, Runnable> cases = new HashMap<T, Runnable>(0);
    public void addCase(T object, Runnable action) {
        this.cases.put(object, action);
    }
    public void SWITCH(T object) {
        for (T t : this.cases.keySet()) {
            if (object.equals(t)) { // This means that the class works with any object!
                this.cases.get(t).run();
                break;
            }
        }
    }
}case我认为语句必须始终是常数,而String.hashCode()并非如此(即使实际上JVM之间的计算从未改变过)。
                    case语句值不必在编译时就可以确定,因此可以很好地工作。
                    多年来,我们一直在使用(n个开源)预处理器。
//#switch(target)
case "foo": code;
//#end预处理后的文件名为Foo.jpp,并使用ant脚本处理为Foo.java。
优点是将其处理为可在1.0上运行的Java(尽管通常我们仅支持1.4)。与使用枚举或其他变通方法进行伪造相比,执行此操作(许多字符串切换)要容易得多-代码更易于阅读,维护和理解。IIRC(目前无法提供统计信息或技术推理)也比自然的Java等效更快。
缺点是您不编辑Java,因此工作流程(编辑,处理,编译/测试)要多一些,并且IDE会链接回Java,这有点麻烦(开关变成一系列if / else逻辑步骤)并且不保持开关箱顺序。
我不建议在1.7+上使用它,但是如果您要编写针对较早JVM的Java(因为Joe public很少安装最新版本的Java),它就很有用。
其他答案表明这是在Java 7中添加的,并提供了较早版本的解决方法。这个答案试图回答“为什么”
Java是对C ++过于复杂的反应。它被设计为一种简单的简洁语言。
String在语言中有一些特殊情况处理,但对我来说似乎很清楚,设计师正在尝试将特殊大小写和语法糖的数量保持在最低水平。
由于字符串不是简单的原始类型,因此打开字符串非常复杂。在设计Java时,这并不是一个普遍的功能,并且实际上与极简主义设计并不十分吻合。特别是因为他们决定对字符串不使用特殊情况==,所以对于==不适用的情况下的大小写工作会有些奇怪。
在1.0和1.4之间,语言本身几乎保持不变。Java的大多数增强功能都在库方面。
Java 5改变了一切,该语言得到了实质性扩展。在版本7和8中进行了进一步的扩展。我希望这种态度的改变是由C#的崛起驱动的
JDK-13中的 JEP 354:开关表达式(预览)和JDK-14中的 JEP 361:开关表达式(标准)将扩展 switch语句,因此可以将其用作表达式。
现在你可以:
case L ->):
“ case L->”开关标签右侧的代码被限制为表达式,块或(为方便起见)throw语句。
为了从switch表达式中产生一个值,
breakwith value语句被删除,转而使用一条yield语句。
  public static void main(String[] args) {
    switch (args[0]) {
      case "Monday", "Tuesday", "Wednesday" ->  System.out.println("boring");
      case "Thursday" -> System.out.println("getting better");
      case "Friday", "Saturday", "Sunday" -> System.out.println("much better");
    }不是很漂亮,但这是Java 6和波纹管的另一种方式:
String runFct = 
        queryType.equals("eq") ? "method1":
        queryType.equals("L_L")? "method2":
        queryType.equals("L_R")? "method3":
        queryType.equals("L_LR")? "method4":
            "method5";
Method m = this.getClass().getMethod(runFct);
m.invoke(this);Groovy轻而易举;我嵌入了groovy jar并创建了一个groovy实用程序类来完成所有这些事情,而我发现这些事情在Java中令人生厌(因为我在企业中一直使用Java 6)。
it.'p'.each{
switch (it.@name.text()){
   case "choclate":
     myholder.myval=(it.text());
     break;
     }}...当您使用intellij时,还请注意:
文件->项目结构->项目
文件->项目结构->模块
如果有多个模块,请确保在“模块”选项卡中设置正确的语言级别。
public class StringSwitchCase { 
    public static void main(String args[]) {
        visitIsland("Santorini"); 
        visitIsland("Crete"); 
        visitIsland("Paros"); 
    } 
    public static void visitIsland(String island) {
         switch(island) {
          case "Corfu": 
               System.out.println("User wants to visit Corfu");
               break; 
          case "Crete": 
               System.out.println("User wants to visit Crete");
               break; 
          case "Santorini": 
               System.out.println("User wants to visit Santorini");
               break; 
          case "Mykonos": 
               System.out.println("User wants to visit Mykonos");
               break; 
         default: 
               System.out.println("Unknown Island");
               break; 
         } 
    } 
}