Java - 为什么char会被隐式地转换为字节(和简短)原语,什么时候不应该?

时间:2013-06-12 10:41:01

标签: java char type-conversion byte implicit-cast

编译器的某些功能让我感到困惑(使用Eclipse的Oracle JDK 1.7)。

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

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

char c = '&';  
byte b = (byte)c;
short s = (short)c;

正确打印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 bt = (byte)'&';
System.out.println(bt); // Correctly displays number 38 on the console

但这个无编译警告字符到字节(和短)“潜行转换”对我来说似乎不对。

有人可以解释,为什么允许这样做?

原因可能在于'<char>'本身的解释,因此它实际上并没有达到char原始状态,而是作为数字(八进制或十六进制等)值处理?

5 个答案:

答案 0 :(得分:6)

这称为编译时缩小常量。它在Java语言规范的第5.2节中描述:

  

常量的编译时缩小意味着代码如:

byte theAnswer = 42;
     

是允许的。没有缩小,整数文字42具有int类型的事实   表示需要转换为字节。

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

例如,这不会编译:

byte bc = '\uff12'; // Does not compile without a cast

但是编译得很好:

byte bc = (byte)'\uff12';

答案 1 :(得分:5)

基本上,specification of assignment conversion指定了

  

另外,如果表达式是常量表达式(§15.28)   输入byte,short,char或int:

     

如果类型为,则可以使用缩小的基元转换   变量是byte,short或char,以及常量的值   表达式可以在变量的类型中表示。

你的'&'正好是“byte,short,char或int”类型的常量表达式。

答案 2 :(得分:1)

  

为什么以下工作也一样?

因为'&'是一个常量表达式,其值适合byte

JLS 14.4.2

  

如果声明符具有初始化表达式,则计算表达式并将其值赋给变量。

JLS 5.2

  

当表达式的值被赋值(第15.26节)给变量时,就会发生赋值转换:必须将表达式的类型转换为变量的类型。

     

...

     

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

     
      
  • 如果变量的类型是byte,short或char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示。
  •   

答案 3 :(得分:1)

我不知道这种解释是否足够,但这种行为是在JLS中定义的。来自JLS, section 5.2

  

另外,如果表达式是a   类型的常量表达式(第15.28节)   byte,short,char或int:

     
      
  • 缩小基元转换可能   如果变量的类型是,则使用   byte,short或char,以及的值   常量表达式是   可代表的类型   变量。
  •   
  • 缩小原语   转换后跟拳击   如果类型为,则可以使用转换   变量是:   
        
    • 字节和值   常量表达式是   在字节类型中可表示。
    •   
    • 短   和常量的值   表达式可以代表   类型短。
    •   
    • 性格和价值   常量表达式是   可以在char。中表示。
    •   
  •   

答案 4 :(得分:0)

表达'&amp;'在变量bc的初始值设定项中是一个常量表达式。变量b和s的初始值设定项中的表达式c不是常量表达式。当上下文需要时,Java执行隐式缩小基元的转换当值是常量表达式的结果时。