Java switch底层只处理int,支持类型须可无歧义映射为int:①byte/short/char/int及对应包装类(自动提升或拆箱);②enum(用ordinal());③String(编译期算hashCode+运行时equals校验),而long因范围超int被禁止。
java 的 switch 语句表面支持多种类型,但底层只处理 int。所有能进 switch 的类型,都必须能被编译器无歧义地映射为一个确定的整数——这是理解支持范围和 string 哈希机制的核心。
哪些类型能用?本质都是“可转成 int”
能用的类型分三类,共同点是:值在编译期可确定,且能安全、唯一地对应一个 int:
- 基本整型及对应包装类:byte、short、char、int,以及 Byte、Short、Character、Integer。其中 byte/short/char 会自动提升为 int;包装类靠自动拆箱后提升。
-
枚举(enum):编译器取其
ordinal()(声明顺序索引,从 0 开始),本质上跳转的是一个整数位置。 -
String(JDK 7+):不是比内容,而是靠编译期预计算每个 case 字符串的
hashCode(),生成整数跳转表;运行时再用equals()校验,防止哈希冲突。
String 进 switch 的真实执行流程
你写的是:
switch (str) {<br> case "apple": ...<br> case "banana": ...<br>}
编译器实际把它重写为两层逻辑:
智能模型自动切换 V5.0.2 - 多模态感知,自动识别图片/视频/音频/代码/文本任务,切换最优模型。支持图片理解(qwen3-vl-plus)、视频音频(qwen3.5-plus)、代码(glm-5)、Office文档(MiniMax-M2.5)、推理等场景。零感知切换,无需手动操作。
- 第一层:调用
str.hashCode(),拿到一个 int,用tableswitch(值密集)或lookupswitch(值稀疏)快速跳转到候选分支块; - 第二层:在对应分支里,插入
if (str.equals("apple"))严格校验——因为不同字符串可能哈希相同(如 "Aa" 和 "BB" 都是 2112),必须兜底。
反编译后常见结构类似:
switch(str.hashCode()) {<br> case 96321: if (str.equals("apple")) { ... } break;<br> case 97314: if (str.equals("banana")) { ... } break;<br>}
为什么 long 不行,String 却可以?
关键不在“是不是引用类型”,而在“能不能无风险映射为 int”:
- long 取值范围远超 int(−2⁶³ ~ 2⁶³−1 vs −2³¹ ~ 2³¹−1),强制截断会丢失高位,导致行为不可预测,JVM 明确拒绝这种隐式转换;
-
String 虽是引用类型,但它的
hashCode()方法稳定返回 int,且所有 case 字面量的哈希值可在编译期算出并固化进 class 文件,配合运行时equals()校验,既高效又语义准确。
几个必须注意的硬约束
这些不是运行时限制,而是编译期强要求:
-
case 必须是编译期常量:比如
"hello"或static final String MSG = "world";new String("x")、"a" + getSuffix()、变量引用(如String s = "x"; case s:)都会直接编译失败。 -
null 不走 default,直接抛 NullPointerException:因为第一步就是
str.hashCode(),null 调用该方法立刻 NPE,根本不会进入 switch 主体。 -
重复 case 值报错:两个相同的字符串字面量(如两个
"abc")会被视为重复标签,编译不通过。

















