以前、Javaのbyte型とint型との変換について勉強するために作成したテストコード。
public class TestByte { public static void main(String[] args) { // Test1 byte byteData = (byte) 0xC7; // 11000111 // If there is no "(byte)", 0xC7 is looked as int. System.out.println(byteData); // -57 // Test2 int intData = 0xC7; // 00000000 00000000 00000000 11000111 System.out.println(intData); // 199 // Test3 int castedData = (int)byteData; // 11111111 11111111 11111111 11000111 System.out.println(castedData); // -57 // Test4 int positiveNumber = byteData & 0xff; // 11111111 11111111 11111111 11000111 & 00000000 00000000 00000000 11111111 // 0xff is looked as int, so this is "int" & "int". // Result: 00000000 00000000 00000000 11000111 System.out.println(positiveNumber); // 199 } }
- Test1: 0xC7 は、byte型だと先頭bitが立っているので、Javaにより負数と解釈される。なお、(byte)のキャストがないと、0xC7はint型と扱われ byteData への代入の際にコンパイルエラーとなる。
- Test2: 0xC7 は、int型だと先頭bitが立っていないので、Javaにより正数と解釈される。
- Test3: 先頭bitが立っているbyte型のデータをint型にキャストすると、拡張された上位bitが全て 1 で埋められ、Javaにより負数と解釈される。
- Test4: byte型のデータをintで(暗黙的に)キャストする際、0xff とのANDを取ると、拡張された上位bitは全て 0 で埋められ、Javaにより正数と解釈される。
ソース解析を行っていて、久々に出くわすと、あれ何だっけ・・?と思ってしまうことがあるので、、ここに纏めてみた。
要は、明示的にも暗黙的にも、byte型をint型にキャストする場合、拡張された上位bitが全て 1 で埋まることがあるので、要注意ということ。これは、byte→int に限らず、型を大きい方向に拡張すると起きる。
普通に数値計算する範囲では問題にはならないと思うが、バイト列を16進ダンプ文字列に変換する処理を書くときなどは、知らないとはまると思う。