为什么xor对常量(字符)的操作在使用变量时的工作方式不同

afz*_*lex 3 c c# c++ java expression

看看下面的代码:

情况1 :

char a = 'x' ^ 'y';
Run Code Online (Sandbox Code Playgroud)

它工作正常.但是当我在这里使用变量而不是常量时:

案例2:

char x = 'x';
char y = 'y';
char a = x ^ y; // Error!
Run Code Online (Sandbox Code Playgroud)

在java语言中:case 1正在工作,a的值为1,但是case 2不起作用.

在C和C++中:两种情况都有效,a的值为1

在C#中:两种情况都不起作用.

在javascript:这两种情况下都工作,这是不是一个HLL和价值出来是0.


我知道java正在将变量转换为整数来进行二进制操作,但是为什么它在情况1中工作而不是在情况2中,为什么在C#中不起作用?为什么在javascript的情况下值不同.

更新 当我使变量最终比它在java中工作时,但仍然不在C#中

final char x = 'x';
final char y = 'y';
char a = x ^ y;
Run Code Online (Sandbox Code Playgroud)

但是我仍然不明白为什么常量工作但是当使用变量时它们不是.为什么其他高级编程语言不会发生同样的情况.
我认为这是一个基本的操作,应该在所有具有相同行为的编程语言中工作.

注意要在javascript中测试所有上述情况,我在所有情况下都将'char'替换为'var'并且它们正在工作.

ysh*_*vit 5

仅回答Java.

表达式'x' ^ 'y'是一个常量表达式 ; x ^ y不是,除非声明两个变量final.而且,结果是int; ^是一个完整的按位运算符,这意味着在评估之前必须将两个操作数提升为整数类型.char促进int.

所以你有这个int表达式,你试着把它缩小到一个char.在一般情况下,这可能会导致精度损失(整数是4个字节,字符是2),因此编译器不会让你这样做而没有明确说明它是你想要做的(通过强制转换char) .但是,如果常量表达式的值适合新类型,则可以隐式缩小常量表达式.从JLS 5.2:

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

(重点补充)

直觉上,这是完全有道理的:错误是告诉你,你可能会失去精确度,所以它要你确认你知道; 从某种意义上说,这是一个响亮的警告.但是如果编译器完全可以知道这不会发生,就像它可以用于常量表达式一样,那么它会使事情变得更容易并且"隐藏"那个警告.