这个功能会被放到后面的Java版本中吗?

有人能解释一下为什么我不能这样做,比如,Java的switch语句工作的技术方式吗?


当前回答

如果代码中有一个地方可以打开String,那么最好将String重构为可能值的枚举,这样就可以打开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;
}

其他回答

从1.7开始直接使用String的例子如下:

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

}

如果您没有使用JDK7或更高版本,可以使用hashCode()来模拟它。因为String.hashCode()通常为不同的字符串返回不同的值,并且总是为相同的字符串返回相同的值,所以它是相当可靠的(不同的字符串可以产生与评论中提到的@Lii相同的哈希代码,例如“FB”和“Ea”)。

所以,代码看起来是这样的:

String s = "<Your String>";

switch(s.hashCode()) {
case "Hello".hashCode(): break;
case "Goodbye".hashCode(): break;
}

这样,你在技术上开启了一个整型。

或者,你可以使用下面的代码:

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

JDK-13中的JEP 354: Switch Expressions(预览)和JDK-14中的JEP 361: Switch Expressions(标准)将扩展Switch语句,使其可以用作表达式。

现在你可以:

直接从开关表达式中分配变量, 使用新形式的开关标签(case L ->): “case L ->”开关标签右侧的代码被限制为表达式、块或(为方便起见)throw语句。 每个大小写使用多个常量,用逗号分隔, 而且也没有更多的价值突破: 为了从switch表达式中产生一个值,用yield语句代替break with value语句。

所以答案(1,2)的演示可能是这样的:

  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 7中添加的,并为早期版本提供了变通办法。这个答案试图回答“为什么”

Java是对c++过于复杂的一种反应。它被设计成一种简单干净的语言。

String在语言中有一些特殊情况的处理,但在我看来很明显,设计师试图将特殊的大小写和语法糖分保持在最低限度。

由于字符串不是简单的基元类型,因此打开字符串实际上是相当复杂的。在设计Java的时候,这并不是一个常见的特性,也不太适合极简设计。特别是当他们决定不为字符串使用特殊case ==时,case在==不工作的情况下工作会有点奇怪。

在1.0到1.4之间,语言本身基本保持不变。对Java的大多数增强都是在库方面。

这一切在Java 5中都有所改变,该语言得到了实质性的扩展。在版本7和8中进行了进一步的扩展。我认为这种态度的转变是由c#的兴起所推动的

多年来,我们一直在为此使用(n个开源)预处理器。

//#switch(target)
case "foo": code;
//#end

预处理文件被命名为Foo.jpp,并使用ant脚本处理为Foo.java。

优点是它被处理成运行在1.0上的Java(尽管通常我们只支持1.4版本)。而且,与使用枚举或其他变通方法相比,这样做(大量字符串开关)要容易得多——代码更容易阅读、维护和理解。IIRC(在这一点上不能提供统计数据或技术推理)也比自然的Java等价物更快。

缺点是你没有编辑Java,所以它有更多的工作流(编辑、处理、编译/测试),加上IDE将链接回Java,这有点复杂(切换变成一系列if/else逻辑步骤),并且切换case顺序没有维护。

对于1.7以上版本,我不推荐使用它,但如果您想编写针对早期jvm的Java程序,它很有用(因为Joe public很少安装最新版本)。

您可以从SVN获取或在线浏览代码。您将需要EBuild按原样构建它。