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

以下是Sun的Java教程的摘录

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

一定有充分的理由说明为什么不允许使用基元数据类型。有人知道它是什么吗?long


答案 1

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

开关基本上可以通过两种方式实现(或者原则上是组合):对于少数情况,或者值广泛分散的情况,开关基本上相当于临时变量上的一系列if(打开的值必须只计算一次)。对于值或多或少连续的中等数量的情况,将使用开关表(Java 中的 TABLESWITCH 指令),从而在表中有效地查找要跳转到的位置。

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


答案 2

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

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

确切地说,2³²是很多情况,任何具有足够长的方法的程序都将是非常可怕的!使用任何语言。(据我所知,在任何语言的任何代码中,最长的函数都是略高于6k SLOC的 - 是的,这是一个很大的函数 - 它真的难以管理。如果你真的被困在一个你应该只有一个或更少的地方,那么你有两个真正的选择。switchlongint

  1. 在哈希函数的主题上使用一些变体将 压缩为 .最简单的一个,只适用于你弄错了类型,就是只施法!更有用的是这样做:longint

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

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

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

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

为了重申带回家的信息,想要在a上表明你的程序中的类型是错误的,或者你正在构建一个涉及如此多变化的系统,你应该使用类。在这两种情况下,是时候重新思考一下了。switchlong