どうしてこれが起こるのですか?
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バイトの値が保持されます。これはどのように起こりますか?
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が型変換で舞台裏で行うことです。これは多くの開発者にとって誤解のよくある領域です。それでもステップと混同されている場合はコメントを投稿してください。
符号拡張 です。 \u1234
ではなく\uffff
を試して、何が起こるかを確認してください。
Java byte
が署名されています。直感に反します。バイトが使用されるほとんどすべての状況では、プログラマーは代わりに符号なしバイトが必要になります。バイトが直接intにキャストされた場合は、バグである可能性が非常に高いです。
これはほとんどすべてのプログラムで意図した変換を正しく行います:
int c = 0xff & b ;
経験的に、符号付きバイトの選択は誤りです。
あなたのマシンで起こっているかなり奇妙なもの。 Java言語仕様の4.2.1章をご覧ください :
整数型の値は、次の範囲の整数です。
バイトの場合、-128から127まで(両端を含む)
...他を切り取る...
JVMが標準に準拠している場合、出力は-1
。