web-dev-qa-db-ja.com

バイトにchar? (Java)

どうしてこれが起こるのですか?

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?

基本的に、charは16ビットであることがわかりました。したがって、それをbyteにキャストすると、データが失われないのはなぜですか? (intにキャストした後の値は同じです)

私のこの無知な質問に答えてくれてありがとう。 :P

編集:うわー、私の元の出力が実際に期待どおりに機能したことがわかりましたが、上記のコードを更新しました。基本的に、文字はバイトにキャストされてからcharにキャストバックされ、元の2バイトの値が保持されます。これはどのように起こりますか?

18
wakachamo

Trojanfoeが述べているように、コードの結果に対する混乱は、一部には符号拡張によるものです。あなたの混乱を助けるかもしれないより詳細な説明を追加しようと思います。

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

ご指摘のとおり、これにより情報が失われます。これは ナローイング変換 と見なされます。 charをバイトに変換すると、「最下位nビットを除くすべてが単純に破棄されます」。
結果は次のとおりです:0xFFFF -> 0xFF

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

バイトをcharに変換することは 特別な変換 と見なされます。実際には2つの変換を実行します。最初に、バイトはSIGN拡張されます(新しい上位ビットは古い符号ビットからコピーされます)からint(通常の拡大変換)に。次に、intは、ナローイング変換を使用してcharに変換されます。
結果は次のとおりです:0xFF -> 0xFFFFFFFF -> 0xFFFF

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

Charをintに変換すると、 拡大変換 と見なされます。 char型が整数型に拡張されると、ゼロ拡張されます(新しい上位ビットは0に設定されます)。
結果は次のとおりです:0xFFFF -> 0x0000FFFF。印刷すると、65535になります。

私が提供した3つのリンクは、公式のJava言語仕様のプリミティブ型変換に関する詳細です。これらを参照することを強くお勧めします。これらはひどく冗長ではありません(この場合は比較的簡単です)。詳細正確にJavaが型変換で舞台裏で行うことです。これは多くの開発者にとって誤解のよくある領域です。それでもステップと混同されている場合はコメントを投稿してください。

26
robert_x44

符号拡張 です。 \u1234ではなく\uffffを試して、何が起こるかを確認してください。

8
trojanfoe

Java byteが署名されています。直感に反します。バイトが使用されるほとんどすべての状況では、プログラマーは代わりに符号なしバイトが必要になります。バイトが直接intにキャストされた場合は、バグである可能性が非常に高いです。

これはほとんどすべてのプログラムで意図した変換を正しく行います:

int c = 0xff & b ;

経験的に、符号付きバイトの選択は誤りです。

6
irreputable

あなたのマシンで起こっているかなり奇妙なもの。 Java言語仕様の4.2.1章をご覧ください

整数型の値は、次の範囲の整数です。

バイトの場合、-128から127まで(両端を含む)

...他を切り取る...

JVMが標準に準拠している場合、出力は-1

0
darioo