Java—当char不应该';T

Java—当char不应该';T,java,char,type-conversion,byte,implicit-conversion,Java,Char,Type Conversion,Byte,Implicit Conversion,编译器的某些功能让我感到困惑(使用Eclipse的OracleJDK1.7) 所以我有本书说char原语需要显式转换为short和byte,这一切都是有意义的,因为数据类型的允许范围不重叠 换句话说,下面的代码可以工作(但如果没有显式类型转换则无法工作): 打印b或s正确显示数字38,这是Unicode中(&)的等效数字 这就引出了我的实际问题。为什么以下方法也能起作用? byte bc = '&'; short sc = '&'; System.out.println(bc);

编译器的某些功能让我感到困惑(使用Eclipse的OracleJDK1.7)

所以我有本书说char原语需要显式转换为short和byte,这一切都是有意义的,因为数据类型的允许范围不重叠

换句话说,下面的代码可以工作(但如果没有显式类型转换则无法工作):

打印b或s正确显示数字38,这是Unicode中(&)的等效数字

这就引出了我的实际问题。为什么以下方法也能起作用?

byte bc = '&';
short sc = '&';
System.out.println(bc); // Correctly displays number 38 on the console
System.out.println(sc); // Correctly displays number 38 on the console
现在,我肯定会理解以下内容(这也适用):

但是这种没有编译器警告的字符到字节(和简短的)“偷偷转换”对我来说似乎不合适

有人能解释一下为什么允许这样做吗?

byte bc = '&';
short sc = '&';
System.out.println(bc); // Correctly displays number 38 on the console
System.out.println(sc); // Correctly displays number 38 on the console
原因可能是对
'
本身的解释,因此它实际上不会进入char原语状态,而是作为数字(八进制或十六进制等)值处理

为什么下面的方法同样有效

因为
“&”
是一个常量表达式,其值适合
字节

JLS 14.4.2

如果一个声明符有一个初始化表达式,则对该表达式求值,并将其值赋给该变量

JLS 5.2

将表达式的值赋给变量(§15.26)时,会发生赋值转换:表达式的类型必须转换为变量的类型

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

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

我不知道这种解释是否足够,但这种行为是在JLS中定义的。从:

此外,如果表达式是 类型的常量表达式(§15.28) 字节、短字符、字符或整数:

  • 可以使用缩小原语转换 如果变量的类型为 字节、短字符或字符,以及 常量表达式为 可表示为 变数
  • 缩小的原语 拳击后的转换 如果 变量为:
    • 字节和值 常数表达式的形式是 可在类型字节中表示
    • 短 以及常数的值 表达式在 输入short
    • 个性与价值 常量表达式为 可在类型char中表示

变量bc的初始值设定项中的表达式“&”是一个常量表达式。变量b和s的初始值设定项中的表达式c不是常量表达式。当上下文需要时,Java对原语执行隐式缩小转换,当值仅是常量表达式的结果时。

基本上,指定

此外,如果表达式为常数表达式(§15.28),则 键入byte、short、char或int:

如果 变量是byte、short或char,以及常量的值 表达式可以用变量的类型表示

您的
&
正是“byte、short、char或int类型的常量表达式”。

这称为常量编译时收缩。Java语言规范第5.2节对此进行了描述:

常量的编译时收缩意味着以下代码:

byte theAnswer = 42;
是允许的。如果不缩小范围,整数文本42具有int类型的事实将 这意味着需要对字节进行强制转换

字符文本也是如此:如果其值适合
字节
,则不需要转换;如果该值不适合,则必须进行强制转换,否则会出现编译错误

例如,这不会编译:

byte bc = '\uff12'; // Does not compile without a cast
但这很好:

byte bc = (byte)'\uff12';

简单地说,编译器可以确定是否可以安全地缩小常数。如果精度丢失,它将生成编译时间错误,请尝试此错误进行比较:字节b='\u20AC';虽然参考是正确的(根据作业规范),但引用的第一段内容并不相关。这些赋值示例中没有参数化类型。只有第二段适用。
byte bc = (byte)'\uff12';