为什么不能在字符串上使用switch语句?
此功能是否将在以后的Java版本中使用?
有人可以解释为什么我不能这样做吗,例如Java的switch
语句的技术方式?
#1楼
Groovy轻而易举; 我嵌入了groovy jar并创建了一个groovy
实用程序类来完成所有这些事情,而我发现这些事情在Java中令人生厌(因为我在企业中一直使用Java 6)。
it.'p'.each{
switch (it.@name.text()){case "choclate":myholder.myval=(it.text());break;}}...
#2楼
多年来,我们一直在使用(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很少安装最新的JVM),它就很有用。
您可以从SVN获得它,也可以在线浏览代码 。 您将需要EBuild才能按原样构建它。
#3楼
从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;}}
#4楼
如果您没有使用JDK7或更高版本,则可以使用hashCode()
进行仿真。 produce the same hash code as @Lii mentioned in a comment, such as "FB"
and "Ea"
) See documentation . 由于String.hashCode()
通常会为不同的字符串返回不同的值,并且始终为相等的字符串返回相等的值,因此这是相当可靠的(不同的字符串生成与注释中提到的@Lii相同的哈希码,例如"FB"
和"Ea"
)参见文档 。
因此,代码如下所示:
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;}}}
}
#5楼
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; } } }
#6楼
带有String
switch语句已在Java SE 7中实现 ,至少在首次提出要求后的 16年。 没有提供延迟的明确原因,但可能与性能有关。
在JDK 7中实现
现在,该功能已通过javac
中的“反糖化”过程实现。 在case
声明中使用String
常量的一种干净的高级语法在编译时扩展为遵循模式的更复杂的代码。 生成的代码使用始终存在的JVM指令。
在编译过程中,具有String
的switch
将转换为两个开关。 第一个将每个字符串映射到一个唯一的整数-它在原始开关中的位置。 这是通过首先打开标签的哈希码来完成的。 相应的情况是一个if
语句,用于测试字符串是否相等; 如果哈希上有冲突,则测试为级联的if-else-if
。 第二个开关在原始源代码中进行镜像,但是用相应的位置替换了大小写标签。 此两步过程使保留原始交换机的流量控制变得容易。
在JVM中切换
有关switch
更多技术深度,可以参考JVM规范,其中描述了switch语句的编译 。 简而言之,有两种不同的JVM指令可用于切换,具体取决于案例使用的常量的稀疏性。 两者都依赖于每种情况下使用整数常量来有效执行。
如果常量是密集的,则将它们用作指令指针表( tableswitch
指令)的索引(减去最小值后)。
如果常量稀疏,则执行二进制搜索以lookupswitch
正确的大小写lookupswitch
指令。
在对String
对象的switch
进行除糖处理时,很可能会使用这两个指令。 lookupswitch
适用于哈希码的第一个开关,以查找案例的原始位置。 产生的序数自然适用于tableswitch
。
两条指令都要求在编译时对分配给每种情况的整数常量进行排序。 在运行时,而O(1)
性能tableswitch
一般都比较好显得比O(log(n))
的性能lookupswitch
,它需要一些分析,以确定该表是否是密集足以证明时空权衡。 Bill Venners写了一篇很棒的文章 ,其中更详细地介绍了此内容,同时还深入介绍了其他Java流程控制指令。
在JDK 7之前
在JDK 7之前, enum
可以近似于基于String
的开关。 这将使用编译器针对每种enum
类型生成的静态valueOf
方法。 例如:
Pill p = Pill.valueOf(str);
switch(p) {case RED: pop(); break;case BLUE: push(); break;
}
#7楼
基于整数的开关可以优化为高效代码。 基于其他数据类型的开关只能编译为一系列if()语句。
因此,C&C ++仅允许在整数类型上进行切换,因为它与其他类型无关。
C#的设计师认为即使没有优势,样式也很重要。
Java的设计师显然像C的设计师那样思考。
#8楼
如果您在代码中有一个可以打开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;
}
#9楼
James Curran简洁地说:“可以将基于整数的开关优化为非常有效的代码。基于其他数据类型的开关只能编译为一系列if()语句。因此,C&C ++仅允许对整数类型进行开关,因为它与其他类型毫无意义。”
我的观点(仅此而已)是,一旦您开始启用非基本体,就需要开始考虑“等于”与“ ==”。 首先,比较两个字符串可能是一个相当漫长的过程,从而增加了上面提到的性能问题。 其次,如果需要打开字符串,则需要忽略大小写的字符串,考虑/忽略语言环境的字符串,基于正则表达式的字符串...。我赞成这样的决定,即该决定节省了很多时间。语言开发人员会以少量的时间为程序员付出代价。
#10楼
除了上述良好的论据外,我还要补充一点,今天很多人都将switch
视为Java程序过时的剩余部分(回到C时代)。
我没有完全同意这种观点,我认为switch
在某些情况下可能会有用,至少是因为它的速度,而且无论如何, else if
我在某些代码中看到的else if
,它比一系列级联的数字要好。
但是确实,值得一看的是您需要一个开关的情况,看看是否不能用更多的OO代替它。 例如Java 1.5+中的枚举,也许是HashTable或其他一些集合(有时我很遗憾,我们没有作为一流公民的(匿名)函数,如Lua(没有开关)或JavaScript)或什至是多态。
#11楼
当您使用intellij时,还请注意:
文件->项目结构->项目
文件->项目结构->模块
如果有多个模块,请确保在“模块”选项卡中设置正确的语言级别。
#12楼
其他答案表明这是在Java 7中添加的,并提供了较早版本的解决方法。 这个答案试图回答“为什么”
Java是对C ++过于复杂的反应。 它被设计为一种简单的简洁语言。
String在语言中有一些特殊情况处理,但对我来说似乎很清楚,设计师正在尝试将特殊大小写和语法糖的数量保持在最低水平。
由于字符串不是简单的原始类型,因此打开字符串非常复杂。 在设计Java时,这不是一个常见的功能,因此与极简设计并不十分吻合。 尤其是因为他们决定对字符串不使用特殊情况==,对于==不适用的情况下的大小写工作会有些奇怪。
在1.0和1.4之间,语言本身几乎保持不变。 Java的大多数增强功能都在库方面。
Java 5改变了一切,该语言得到了实质性扩展。 在版本7和8中进行了进一步的扩展。我希望这种态度的改变是由C#的崛起驱动的
#13楼
不是很漂亮,但这是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);
#14楼
以下是基于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}
}
为什么不能在字符串上使用switch语句?相关推荐
- java switch语句与switch表达式区别及使用
1.switch语句 与if/else语句不同,switch语句可以有许多可能的执行路径.switch可用于基本类型byte.short.char和int.它们各自的包装类型(byte.short.C ...
- linux脚本中swith,BeanShell中switch语句
我的博客原址关于更多BeanShell的博文请单击此处 在 BeanShell 中,switch 语句不仅仅可以接收数值类型的参数还能传入对象类型.比如,你可以 switch 日期和字符串,相当于使用 ...
- 如何在Ruby中编写switch语句
如何在Ruby中编写switch语句? #1楼 案例...当 在Chuck的答案中添加更多示例: 带参数: case a when 1puts "Single value" whe ...
- Think in java(四)枚举类enum的基本特性、构造方法与方法覆盖、Switch语句中的enum运用
一.基本enum特性 package test;enum Fruit{PEACH,LEMON,BANANA,Apple}public class EnumClasstest {public stati ...
- c 语言switch结尾,C存在fall through的switch语句
8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? switch语句的一般形式如下:1 2 3 4 5switch(表达式){ case 常量表达式:零条或多条语句 cas ...
- c语言入门----详解分支语句(switch语句)
目录标题 前言 一.为什么会有switch语句 二.switch语句的基本形式 三.switch语句中的break 1.为什么会有break语句 2.break语句的使用 四.switch语句中的de ...
- 在switch语句中使用字符串以及实现原理
一次机缘巧合,在idea中调试代码的时候,跳到了.class文件中,刚好调试的代码是switch,于是就有了下面的内容: 对于Java语言来说,在Java 7之前, switch语句中的条件表达式的类 ...
- 透过IL看C# (1)——switch语句(上)
透过IL看C# (1) switch语句(上) 原文地址:http://www.cnblogs.com/AndersLiu/archive/2008/11/03/csharp-via-il-switc ...
- switch语句能否作用在byte上,能否作用在long上,能否作用在String上?
可以用 char, byte, short, int,Character, Byte, Short, Integer String, enum 不能用 Long,boolean,float,doubl ...
最新文章
- grep之字符串搜索算法Boyer-Moore由浅入深(比KMP快3-5倍)
- eclipse设置java虚拟机内存大小
- 学习旧岛小程序 (3)组件的样式
- html中下拉列表监听事件,ExtJS 下拉框监听事件、日期选择器监听事件、实现动态给items添加删除数据...
- POJ 2516 -- Minimum Cost (最小费用最大流, 必须分开建图)
- C++ dll的隐式与显式调用
- Redis作者谈Redis应用场景
- 软件工程1916|W(福州大学)_助教博客】助教总结
- linux调度器(八)——实时调度与SMP
- opencv+海康威视网络摄像头实时预览+抓图(环境配置加程序)
- AndroidStudio 设置全局查找快捷键
- nslookup查询域名系统服务器,域名解析系统DNS诊断命令nslookup详解
- 数据中台建设(四):企业构建数据中台评估
- 《小狗钱钱》--chapter14~18--生活顺风顺水了起来
- 数据结构 —— 队列、栈、链表的区别
- int型整数的数值范围
- 数字图像处理01:imadjust函数的Pyhton实现
- Leetcode575(力扣575):分糖果
- Error while executing: am startservice ***/com.android.tools.fd.runtime.InstantRunS
- 金蝶EAS管理控制台一闪而过