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

以下是Sun的Java教程摘录:

一个开关与byteshortcharint原始数据types一起工作。 它也适用于枚举types(在类和inheritance中讨论)以及一些特殊的类,它们包装特定的基本types: CharacterByteShortInteger (在Simple Data Objects中讨论)。

为什么不允许long原始数据types,这是一个很好的理由。 有人知道这是什么吗?

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

一个交换机本质上可以用两种方式来实现(或者原则上是一种组合):对于less数情况,或者其值分布很广的情况,交换机本质上等价于临时variables上的一系列if值只能被评估一次)。 对于中等数量的或多或less连续的情况,使用切换表(Java中的TABLESWITCH指令),由此在表中有效地查找跳转到的位置。

这些方法中的任何一个原则上都可以使用长整型值而不是整数。 但是我认为这可能只是一个实际的决定,要平衡指令集和编译器的复杂性与实际需求:真正需要切换一个很长的情况是非常罕见的,必须重写为一系列IF语句,或者以其他方式工作(如果所讨论的长整型值相近,则可以在Java代码中将整数结果减去最小值)。

因为他们没有在字节码中实现必要的指令,而且你真的不想写这么多的情况,所以无论你的代码如何“准备就绪”

[编辑:从这个答案的评论中提取,有一些补充在背景]

确切地说,2³²是很多的情况下,任何一个方法足够长的持续时间将是非常可怕的! 用任何语言。 (我知道在任何语言的任何代码中最长的函数是有点超过6k SLOC – 是的,这是一个很大的switch – 这是真的难以pipe理。)如果你真的坚持在一个long地方,你应该只有一个int或更less,那么你有两个真正的select。

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

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

    然后打开结果。 你必须弄清楚如何改变你正在testing的案例。 但实际上,这还是很糟糕的,因为它没有解决很多案件的真正问题。

  2. 如果您处理大量案例,更好的解决scheme是将您的devise更改为使用Map<Long,Runnable>或类似的东西,以便查找如何分派特定值。 这样可以将案例分成多个文件,在案例数量大的时候更容易pipe理,尽pipe组织实施类主机的注册变得更加复杂(注释可能会帮助您自动build立注册码)。

    FWIW,我在多年前做了这个工作(我们切换到新发布的J2SE 1.2中),当构build一个自定义的字节码引擎来模拟大规模并行硬件时(不,重用JVM由于根本上不合适不同的价值和执行模式),它极大地简化了与C代码使用的大switch相关的代码。

为了重申回家的信息,想要switch一个long时间,表明你的程序中的types是错误的,或者你正在构build一个包含很多变化的系统,你应该使用类。 无论是哪种情况,都需要重新思考。

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

在32位体系结构中,用两个字来表示 。 现在想象一下,如果由于同步不足而导致可能发生的情况,switch语句的执行会观察到一个长32位的高字节和32个低字节的字节! 它可以尝试去…谁知道在哪里! 基本上随机的地方。 即使这两个写法都代表了switch语句的有效情况,但它们的有趣组合可能不会导致第一个也不会导致第二个 – 或者更糟糕的是,它可能会导致另一个有效但无关的情况!

至less使用int(或更less的types),不pipe你搞得多糟糕,switch语句至less会读取某个实际写入的值,而不是“空虚的”值。

当然,我不知道真正的原因(已经超过15年了,我没有注意那么长时间!),但是如果你意识到这样的结构是不安全和不可预测的,那么你会同意这是一个绝对很好的理由不会有长时间的开关(和长期打算 – 将有32位机器,这个原因将保持有效)。