字符到字节?(爪哇)

2022-09-01 16:58:04

为什么会发生这种情况:

char a = '\uffff'; //Highest value that char can take - 65535
byte b = (byte)a; //Casting a 16-bit value into 8-bit data type...! Isn't data lost here?
char c = (char)b; //Let's get the value back
int d = (int)c;
System.out.println(d); //65535... how?

基本上,我看到a是16位。因此,如果您将其转换为 ,为什么没有数据丢失?(转换为整型后的值相同)charbyte

提前感谢您回答我的这个无知的小问题。:P

编辑:哇,发现我的原始输出实际上按预期进行,但我刚刚更新了上面的代码。基本上,字符被转换为一个字节,然后又被转换回一个字符,并保留其原始的 2 字节值。这是如何发生的?


答案 1

正如 trojanfoe 所说,你对代码结果的混淆部分是由于符号扩展。我会尝试添加更详细的解释,这可能有助于解决您的困惑。

char a = '\uffff';
byte b = (byte)a;  // b = 0xFF

如您所见,这确实会导致信息丢失。这被视为缩小转换范围。将 char 转换为字节“只需丢弃除 n 个最低阶位之外的所有位”。
结果是:0xFFFF -> 0xFF

char c = (char)b;  // c = 0xFFFF

将字节转换为字符被视为特殊转换。它实际上执行两次转换。首先,将字节进行 SIGN 扩展(从旧符号位复制新的高阶位)转换为 int(正常加宽转换)。其次,将 int 转换为具有窄转换的字符。
结果是:0xFF -> 0xFFFFFFFF -> 0xFFFF

int d = (int)c;  // d = 0x0000FFFF

将 char 转换为 int 被视为加宽转换。当 char 类型加宽为整数类型时,它是零扩展的(新的高阶位设置为 0)。
结果是:。打印时,这将为您提供65535。0xFFFF -> 0x0000FFFF

我提供的三个链接是关于基元类型转换的官方 Java 语言规范详细信息。我强烈建议你看一看。它们不是非常冗长(在这种情况下相对简单)。它详细说明了java将在幕后对类型转换执行的操作。这是许多开发人员误解的常见领域。如果您仍然对任何步骤感到困惑,请发表评论。


答案 2

这是标志扩展。尝试而不是,看看会发生什么。\u1234\uffff