Javaのbyte型を使ってみる。

基本的な事ですが、byte[]を使う必要に迫られました、、
個人的にとても苦手な所なので、克服するために1つずつJavaの「byte」について調べてみました。

まず「wiki」を見てみました。
Javaのbyteはintやshort等と同じ基本型といわれるもので、
その中でも整数型として提供されているようです。
符号付きの8bitで1000 0000 (-128) 〜 0111 1111 (+127)まで表現できます。

デフォルト値 サイズ 範囲
byte 0 8bit符号付き -128〜127


あとはどんどん色々な使い方を試して探っていくこととします。
以下はbyte型の変数に整数の127を代入して出力するコードです。

public class TestByte {
	public static void main(String[] args) {		
		// Javaのbyte型
		// 10000000 01111111までを表現可能
		// 整数型の為、値は10進数で保持します。
		byte bval = 127;
		System.out.println(bval);	
	}
}
//[実行結果] 127



「127」が表示されました、「byte」の名前に惑わされましたが整数型ですもんね。
ちなみにbyte型の扱える範囲以上の128を代入しようとするとエラーになります。
クイックフィックスが型をintに変えるかい? それとも128を(byte)でキャストするかい?と聞いてきます。


ちなみに強引に以下のようにキャストすると、

byte bval = (byte) 128;
System.out.println(bval);
[実行結果] -128

「-128」が表示されました。129を代入すると「-127」が表示され、
1ずつ増えていきます。127を超える表示になったら-128に戻り、
127〜-128の範囲内でこれを延々と繰り返すようです。


次は整数の「127」をIntegerクラスのメソッドで2進数と16進数形式で出力してみました。

public class TestByte {
	public static void main(String[] args) {		

		// 10進数127の場合、2進数では 0111 1111になる
		// 0111は 16進数で7、1111は 16進数でfになる。
		// 出力は7fになる。
		byte bval1 =  (byte)127;
		System.out.println("(byte)127を出力");
		System.out.println("10進数表現:"+ bval1);
		System.out.println("2進数表現:"+Integer.toBinaryString(bval1));		
		System.out.println("16進数表現:"+Integer.toHexString(bval1));
		System.out.println("16進数表現2桁:"+String.format("%02x", bval1));
	}
}


[実行結果]
(byte)127を出力
そのまま出力(10進数表現):127
2進数表現:1111111
16進数表現:7f
16進数表現2桁:7f

toBinaryStringの結果で最上位ビットが「0」の場合は省略されて7桁になってますね。


上記のコードを少し変えて、負の値「-4」を代入すると、

		byte bval1 =  (byte)-4;
		System.out.println("(byte)-4を出力");
		System.out.println("10進数表現:"+ bval1);
		System.out.println("2進数表現:"+Integer.toBinaryString(bval1));		
		System.out.println("16進数表現:"+Integer.toHexString(bval1));
		System.out.println("16進数表現2桁:"+String.format("%02x", bval1));



こんな結果になります。1がいっぱい

[実行結果]
(byte)-4を出力
10進数表現:-4
2進数表現:11111111111111111111111111111100
16進数表現:fffffffc
16進数表現2桁:fc



toBinaryStringのJavaDocを確認すると以下のように書いてあります。
2の32乗を加算した結果、1が埋められたようです。
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/lang/Integer.html#toBinaryString(int)

整数の引数の文字列表現を、基数 2 の符号なし整数として返します。
引数が負の数の場合は、符号なし int 値は引数に 2の32乗を加算した値になります。そうでない場合は、引数に等しい値になります。この値は、2 進数 (基数 2) の ASCII 文字列に変換されます。前に 0 は付きません。符号なしの絶対値がゼロの場合は、単一のゼロ文字「0」(「\u0030」) で表されます。そうでない場合は、符号なしの絶対値を表す文字の 1 文字目はゼロではありません。2 進数の桁には、「0」(「\u0030」) および「1」(「\u0031」) が使用されます。



byte型は8進数、16進数のリテラルを代入することもできます。
試しに10進数で153を表す0x99を代入してみます。

		// 16進リテラルも代入可能
		// 0x99を代入した場合、10進数では153となるが、
		// byte型の扱える範囲を超えるのでそのままだと負の値が出力される。
		byte bval1 =  (byte)0x99;
		System.out.println("(byte)0x99を出力");
		System.out.println("10進数表現:"+ bval1);
		System.out.println("2進数表現:"+Integer.toBinaryString(bval1));		
		System.out.println("16進数表現:"+Integer.toHexString(bval1));
		System.out.println("16進数表現2桁:"+String.format("%02x", bval1));

出力時にはbyteで扱える範囲を超えているので負の値が表示されてしまいます。

[実行結果]
(byte)0x99を出力
10進数表現:-103
2進数表現:11111111111111111111111110011001
16進数表現:ffffff99
16進数表現2桁:99



これを10進数153として表示するには以下のようにします。

		System.out.println(bval1 & 0xff);



上記は何をしてるかというと、
変数「bval1」と正の整数255を表す16進数リテラル「0xff」のAND演算をして、
正の値に変換しています。

11111111 11111111 11111111 10011001 (bval1)
00000000 00000000 00000000 11111111 (0xff ) AND

                                                                                                              • -

00000000 00000000 00000000 10011001 結果 正の値に戻る。



あとはこれが単純に配列になっただけなので、こんな感じに利用できます。

		byte bval1[] = { (byte)0x77, (byte)0x88, (byte) 0x99 };
		System.out.println("bval1[]を出力");
		for(int i=0; i < bval1.length ; i++){
			System.out.println("10進数表記:"+ (bval1[i] & 0xff));
			//System.out.println("16進数表記"+ String.format("0x%02x", bval1[i]));
		}