2011-02-10 4 views
12

がどのように来るこれが起こる:Char into into byte? (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

EDIT:Woahは、私のオリジナル出力が実際に期待どおりに行ったことを知ったが、私はちょうど上記のコードを更新した。基本的に、文字は1バイトにキャストされ、次にcharにキャストされ、元の2バイトの値が保持されます。これはどうやって起こるのですか?

+1

「-1」が表示されます。 – darioo

+0

は-1をここに印刷します。 – Bozho

+0

ここでも-1が印刷されます。 –

答えて

19

トロイの木馬が述べているように、コード結果に混乱は、部分的に符号拡張によるものです。私はあなたの混乱に役立つかもしれないより詳細な説明を追加しようとします。

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

これが原因で情報が失われることがあります。これはnarrowing conversionとみなされます。 charをバイトに変換することは、 "単純にn個の最下位ビット以外のすべてを破棄します"。
結果は次のとおりです。0xFFFF -> 0xFF

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

special conversionを考えられている文字にバイトを変換します。それは実際に2回の変換を実行します。最初に、バイトはSIGN拡張されます(新しい上位ビットは古い符号ビットからコピーされます)。int(通常の拡大変換)。次に、intは変換が狭いcharに変換されます。
結果は:0xFF -> 0xFFFFFFFF -> 0xFFFF

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

intへチャーがwidening conversion考えられる変換します。char型を整数型に拡張すると、ゼロ拡張されます(新しい上位ビットは0に設定されます)。
結果は0xFFFF -> 0x0000FFFFです。

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

8

これはsign extensionです。 \uffffの代わりに\u1234を試してみて、何が起こるかを見てください。

0

あなたのマシンではかなり奇妙なものがあります。 Java language specification, chapter 4.2.1を見てみましょう:

整数型の値が 次の範囲の整数です:

包括バイトの場合

、-128から127に、...スニップその他...

JVMが標準に準拠している場合、出力は-1である必要があります。

5

java byteに署名しました。それは直観に反する。バイトが使用されているほぼすべての状況では、プログラマは符号なしバイトを必要とします。バイトがintに直接キャストされるとバグが発生する可能性が非常に高くなります。

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

int c = 0xff & b ; 

経験的には、符号付きバイトの選択は間違いです。