char和具有最终访问修饰符的字节 – java

请看下面的示例我无法理解char和byte之间的关系

byte b = 1; char c = 2; c = b; // line 1 

给我编译错误,因为c是char类型,b是byte类型,所以在这种情况下必须强制转换

但现在这里的推文是我在代码下运行的时候

 final byte b = 1; char c = 2; c = b; // line 2 

第2行编译成功它根本不需要任何转换所以我的问题是为什么当我使用带有byte最终访问修饰符时, char c表现不同

因为使用final限定它会使变量成为常量变量,这是一个常量表达式 。 所以

 final byte b = 1; char c = 2; c = b; // line 2 

实际上成了

 final byte b = 1; char c = 2; c = 1; 

并且编译器保证值1可以适合char变量。

对于非常量byte变量,没有这样的保证。 byte是有符号的, char是无符号的 。

您正在使用JLS-5.1.4扩展和缩小原始转换 ,

以下转换结合了扩展和缩小基元转换:

  • byte to char

首先,通过扩展原语转换(第5.1.2节 )将byte转换为int ,然后通过缩小基元转换(第5.1.3节 )将结果int转换为char

 final byte b = 1; char c = (char) ((int) 2); // <-- 2 is an int literal c = (char) ((int) 1); // <-- b is 1 a byte literal 

如果用javap -v检查字节码,你会看到值1在编译后已经替换了变量b

 public static void main(java.lang.String[]) throws java.lang.Exception; descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Exceptions: throws java.lang.Exception Code: stack=2, locals=3, args_size=1 0: iconst_1 1: istore_1 // b = 1 2: iconst_2 3: istore_2 // c = 2 4: iconst_1 // integer1. 5: istore_2 // c = 1. 

我想这是因为java编译器用它们的值替换了对final变量的引用(几乎就像C中的预处理器)。 由于值1对于char类型是合法的,因此最后一行被转换为

 c = 1; 

这是成功编译的。