Why can't I use switch statement on a String?
这个功能会被放到稍后的Java版本中吗?
有人能解释为什么我不能这样做,就像Java的EDCOX1 0语句的技术方法一样吗?
使用EDCOX1,0个实例的开关语句在Java SE 7中实现,至少在16年后被请求。没有提供延迟的明确原因,但可能与性能有关。
在JDK 7中实现该功能现在已经在
在编译过程中,带有
有关
如果常量很密集,则将它们用作索引(减去最小值后)到指令指针表中,即
如果常量是稀疏的,则执行二进制搜索以查找正确的大小写—
在对
这两条指令都要求在编译时对分配给每个事例的整型常量进行排序。在运行时,虽然
在JDK7之前,
1 2 3 4 5 | Pill p = Pill.valueOf(str); switch(p) { case RED: pop(); break; case BLUE: push(); break; } |
如果代码中有一个可以打开字符串的位置,那么最好将该字符串重构为可以打开的可能值的枚举。当然,您可以将字符串的潜在值限制为枚举中可能需要或不需要的值。
当然,枚举可以有一个"other"的条目和一个fromstring(string)方法,然后可以有
1 2 3 4 5 6 7 8 | 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的POST的完整示例,使用JavaEnm而不是使用自定义方法。
请注意,在JavaSE 7中,稍后可以在Switter语句的表达式中使用String对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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&AMP+C++只允许对整数类型进行切换,因为它与其他类型无关。
C的设计师认为,即使没有优势,风格也很重要。
JAVA的设计者显然像C设计师一样思考。
还可以显示自1.7起直接使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
JamesCurran简明扼要地说:"基于整数的开关可以优化为非常有效的代码。基于其他数据类型的开关只能编译为一系列if()语句。出于这个原因,C&AMP+C++只允许对整数类型进行切换,因为它与其他类型毫无意义。
我的观点是,只要你开始打开非原语,你就需要开始思考"等于"和"=="。首先,比较两个字符串是一个相当长的过程,这增加了上面提到的性能问题。其次,如果要打开字符串,则需要打开字符串忽略大小写、打开字符串考虑/忽略区域设置、打开基于regex的字符串….我赞成这样一个决定,即以程序员的少量时间为代价,为语言开发人员节省大量时间。
除了上述好的论点外,我还要补充的是,今天很多人把EDOCX1 0作为Java程序过时的剩余部分(回到C次)。
我不完全同意这一观点,我认为
但事实上,这是值得一看的情况下,你需要一个开关,看看它是否可以取代更多的OO。例如Java 1.5 +中的枚举,也许是哈希表或一些其他集合(有时我很遗憾我们没有(匿名)函数作为第一类公民,如在Lua中没有交换或JavaScript)甚至多态性。
如果不使用JDK7或更高版本,可以使用
所以,代码应该是这样的:
1 2 3 4 5 6 | String s ="<Your String>"; switch(s.hashCode()) { case"Hello".hashCode(): break; case"Goodbye".hashCode(): break; } |
这样,从技术上讲,您可以打开一个
或者,您可以使用以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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; } } } } |
Other answers have said this was added in Java 7 and given workarounds for earlier versions.这个答案试图回答"为什么"
Java was a reaction to the over-complexities of C++.它是一种简单的语言。
严格地说,在语言上有一点特殊的案例处理比特,但对我来说似乎很清楚的是,设计师试图将更多的特殊套管和句法糖保持在最低限度。
自从弦乐不是简单的原始类型以来,弦乐上的开关是公平的复合物。这不是Java时代的一个共同特征,也不是以最低限度的设计来实现的。特别是当他们决定不去特别案件====为了弦乐,它将是(并且是)一个非常陌生的比特,以便在工作地点====doesn't。
在1.0和1.4之间,语言本身也很漂亮。对爪哇的增强大部分在图书馆的一侧。
所有的语言都随着爪哇5号的变化而发生了很大的变化。在第7和第8版中进一步扩展。我希望这一态度的改变是由C 35的崛起驱动的。
多年来,我们一直在为此使用(n个开源)预处理器。
1 2 3 | //#switch(target) case"foo": code; //#end |
预处理的文件名为foo.jpp,并使用Ant脚本处理为foo.java。
优点是它被处理成Java,运行在1(虽然通常我们只支持返回到1.4)。此外,与使用枚举或其他解决方法来缓冲代码相比,执行此操作(许多字符串开关)要容易得多——代码更易于阅读、维护和理解。IIRC(在这一点上不能提供统计或技术推理)它也比自然的Java等价物快。
缺点是你不编辑Java,所以它有更多的工作流程(编辑,处理,编译/测试)加上IDE会链接回Java,这有点复杂(交换机变成一系列的I/EL逻辑步骤),并且交换机的情况不被维护。
我不建议它用1.7 +,但是如果你想把Java瞄准早期JVM(因为乔公众很少有最新安装的),那么它是有用的。
您可以从SVN获取它或在线浏览代码。您将需要ebuild来构建它。
不是很漂亮,但这里是Java 6和Bellow的另一条路:
1 2 3 4 5 6 7 8 |
在Groovy中是微风;我嵌入了Groovy jar并创建了一个EDCOX1×3的实用工具类来完成所有这些事情,而且更多的是我在Java中感到恼火(因为我在Java中被困在企业中使用Java 6)。
1 2 3 4 5 6 | it.'p'.each{ switch (it.@name.text()){ case"choclate": myholder.myval=(it.text()); break; }}... |
当你使用情报时
文件>工程结构>工程
文件>工程结构>模块
当你有多个模块时,确保你在Tab模块中设置正确的语言水平。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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; } } } |