繁体   English   中英

为什么你的 switch 语句数据类型不能很长,Java?

[英]Why can't your switch statement data type be long, Java?

以下是Sun 的 Java 教程的摘录:

开关适用于byteshortcharint原始数据类型。 它还适用于枚举类型(在类和继承中讨论)和一些“包装”某些原始类型的特殊类: CharacterByteShortInteger (在简单数据对象中讨论)。

不允许long原始数据类型必须有充分的理由。 有人知道这是什么吗?

我认为在某种程度上,它可能是基于典型切换使用的任意决定。

交换机基本上可以通过两种方式实现(或者原则上是组合):对于少数情况,或者其值大范围分散的情况,交换机基本上等同于临时变量上的一系列ifs(打开的值必须只评估一次)。 对于或多或少连续值的中等数量的情况,使用切换表(Java中的TABLESWITCH指令),从而有效地在表中查找要跳转到的位置。

这些方法中的任何一个原则上都可以使用长值而不是整数。 但是我认为将指令集和编译器的复杂性与实际需求进行平衡可能只是一个实际的决定:你真正需要切换很长时间的情况很少见,因此必须重新编写为一系列的IF语句,或以其他方式工作(如果有问题的长值靠得很近,你可以在你的Java代码中切换int减去最低值的结果)。

因为他们没有在字节码中实现必要的指令,你真的不想写那么多的情况,无论你的代码如何“生产就绪”......

[编辑:摘自对此答案的评论,并在背景上添加一些内容]

确切地说,2,32是很多情况下,任何方法都有足够长的时间来容纳更多的东西,这将是非常可怕的! 用任何语言。 (我知道的任何语言的任何代码最长功能略微超过6K SLOC -是的,这是一个很大的switch -这是真的无法控制。)如果你真的坚持与具有正long ,你应该只有一个int或者更少,那么你有两个真正的选择。

  1. 在散列函数的主题上使用一些变体将long压缩为int 最简单的一个,只有当你输入错误时才使用,就是施展! 更有用的是这样做:

     (int) ((x&0xFFFFFFFF) ^ ((x >>> 32) & 0xFFFFFFFF)) 

    在打开结果之前。 你必须弄清楚如何改变你正在测试的案例。 但实际上,这仍然很可怕,因为它没有解决许多案件的真正问题。

  2. 如果您正在处理大量案例,那么更好的解决方案是将您的设计更改为使用Map<Long,Runnable>或类似的东西,以便您查找如何分派特定值。 这允许您将案例分成多个文件,这在案例数量变大时更容易管理,尽管组织所涉及的实现类主机的注册变得更加复杂(注释可能有助于您自动构建注册码)。

    FWIW,我多年前做过这个(我们在项目中转换到新发布的J2SE 1.2部分)来构建用于模拟大规模并行硬件的自定义字节码引擎(不,重复使用JVM因为从根本上不合适)所涉及的不同的值和执行模型)并且它极大地简化了代码的C版本所使用的大型switch的代码。

要重申带回家的消息,想要switch一个long消息表明你的程序中的类型错误,或者你正在构建一个涉及你应该使用类的那么多变化的系统。 在任何一种情况下重新考虑的时间。

因为查找表索引必须是32位。

我碰巧遇到了这个 12 岁的问题,我可以为这个问题提供最好的解决方案之一,即使用最新的 jdk,因为 long 和 Long 现在在 switch-case 语句中得到支持。 :)

长的32位体系结构由两个单词表示 现在,想象一下如果由于同步不足会发生什么情况,switch语句的执行会观察到一次写入时高32位,另一次写入低32位! 它可以尝试去....谁知道在哪里! 基本上是随意的某个地方。 即使两个写入代表switch语句的有效情况,它们的有趣组合也可能既不会导致第一个也不会导致第二个 - 或者更糟糕的是,它可能导致另一个有效但无关的情况!

至少对于一个int(或更小的类型),无论你多么糟糕,switch语句至少会读取某人实际编写的值,而不是“凭空”的值。

当然,我不知道实际的原因(已经超过15年,我没有注意那么久!),但是如果你意识到这样一个结构可能是多么不安全和不可预测,你会同意的这是一个绝对非常好的理由永远不会切换多头(并且由于长打算 - 将会有32位机器,这个原因仍然有效)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM