为什么在整数包装器上的Java切换中,“char”案例不编译,但当切换到Byte时编译是正常的?

为什么在整数包装器上的Java切换中,“char”案例不编译,但当切换到Byte时编译是正常的?,java,java-8,switch-statement,Java,Java 8,Switch Statement,不编译: void test(Integer x) { switch (x) { case 'a': } } 编译OK: void test(Byte x) { switch(x) { case 'a': } } 原因相当复杂,但是如果您喜欢Java语言规范的话,它们都在细节中 首先,以下是关于switch语句的说明: 与switch语句关联的每个case常量的赋值必须与switch语句表达式的类型兼容

不编译:

void test(Integer x) {
      switch (x) {
          case 'a':
      }
}
编译OK:

void test(Byte x) {
      switch(x) {
          case 'a':
      }
}

原因相当复杂,但是如果您喜欢Java语言规范的话,它们都在细节中

首先,以下是关于switch语句的说明:

与switch语句关联的每个case常量的赋值必须与switch语句表达式的类型兼容

这意味着“a”需要分别分配给整数和字节

但这听起来并不正确:

您可能会认为,因为“a”应该可以赋值给整数,因为char->int赋值是合法的。任何字符值都将适合整数

您可能会认为,由于char->Byte赋值是不合法的,所以“a”不应该分配给字节。大多数字符值不能放入一个字节

事实上,这两种说法都不正确。为了理解原因,我们需要阅读作业上下文中允许的内容

分配上下文允许使用以下内容之一:

身份转换§5.1.1 a扩大原语转换§5.1.2 拓宽参考转换§5.1.5 加宽参照转换后进行取消装箱转换 先进行加宽引用转换,然后进行取消装箱转换,然后再进行加宽基元转换 装箱转换§5.1.7 装箱转换之后是加宽参照转换 拆箱转换§5.1.8 先进行取消装箱转换,然后再进行加宽原语转换。 要从“a”变为整数,我们需要将char值加宽为int,然后将int框成整数。但是,如果查看允许的转换组合,则不能先进行加宽原语转换,然后再进行装箱转换

因此,不允许将“a”转换为整数。这解释了第一种情况下的编译错误

您可能会认为“a”到字节是不允许的,因为这将涉及原语的缩小转换。。。这根本不在清单上。事实上,文字是一种特殊情况。接着说了下面的话

此外,如果表达式是byte、short、char或int类型的常量表达式:

如果变量的类型为byte、short或char,并且常量表达式的值可以用变量的类型表示,则可以使用窄化原语转换

如果变量的类型为Byte、Short或Character,并且常量表达式的值分别以Byte、Short或char类型表示,则可以使用先进行缩小原语转换,然后进行装箱转换

第二项适用于“a”到字节,因为:

字符文字是一个常量表达式,并且 “a”的值是97位小数,在字节-128到+127的范围内。 这解释了为什么在第二个示例中没有编译错误


1-我们不能将“a”框为字符,然后将字符加宽为整数,因为字符不是整数的Java子类型。如果源类型是目标类型的子类型,则只能使用加宽引用转换

整数是4字节,而字符是2字节。所以在第一种情况下,不管你写什么字符,它都小于整数。但是,在第二种情况下,您编写的字符可能大于最大字节,从而使该情况永远无法执行。这种解释是不正确的。实际上,在第二个示例中,“a”情况下的代码将在x是字节97的情况下执行。如果你不相信我,试试看。关于真正的解释,请参见我的答案。我们可以使用int作为开关类型吗?因为char->int是允许的基本加宽