2026年2月21日土曜日

【Java進化史 番外編】Java8で「符号なし」が追加?本当か?

【Java進化史 番外編】Java8で「符号なし」が追加?本当か?

そういえば。

Java8で「符号なし」が導入された、と どこかで聞いたことがある。

……え?

Javaって、unsigned無かったよね?

なんで今頃?

ちょっと気になったので、調べてみた。


■ きっかけは、IPアドレス

昔、こんなコードを書いたことがある。


InetAddress addr = InetAddress.getLocalHost();
byte[] ip = addr.getAddress();

System.out.println(ip[0]);

出力:


-64

……は?

IPアドレスって、192とか168じゃなかったか?

なぜマイナスになる?


■ 192って何なのか

例として、


192.168.0.1

この「192」は、 IPアドレスの最初の1バイト(8ビット)である。

IPv4は32ビット。


8ビット × 4 = 32ビット

つまり、IPアドレスは4つのbyteでできている。

192を2進数にすると:


11000000

これが1バイトの正体だ。


■ なぜ -64 になるのか

Javaのbyteは符号付き。


-128 ~ 127

11000000を符号付きとして解釈すると、 それは -64 になる。

それだけの話である。


■ Java8ならどう書く?

IP取得方法は変わっていない。 InetAddressも昔のままだ。

変わったのは、読み方である。


InetAddress addr = InetAddress.getLocalHost();  
byte[] ip = addr.getAddress();                  

int first = Byte.toUnsignedInt(ip[0]);

System.out.println(first);

Java8で追加された Byte.toUnsignedInt() によって、 符号なしとして読むことができるようになった。


■ 4つ並べると


for (byte b : ip) {
    System.out.print(b + ".");
}

-64.-88.0.1.

Java8


for (byte b : ip) {
    int value = Byte.toUnsignedInt(b);
    System.out.print(value + ".");
}

192.168.0.1.

■ で、結局なにが起きたのか

Java8は、unsigned型を追加したわけではない。

unsignedとして「読む方法」を追加した。

byteの仕様は変わっていない。 intの仕様も変わっていない。

もちろん、boxingやラッパークラスの挙動もそのままである。

既存のコードを一切壊さない。

その範囲でできることを追加した。

値そのものは昔から同じ。

型は増やさず、 解釈の手段だけを加えた。


■ なぜ今頃?(少しだけ補足)

Javaは当初、型を増やさない設計を選んだ。

だからunsignedは入らなかった。

だが、 ネットワークやビット演算の現場では、 0~255として扱いたい場面が多かった。

そこでJava8で、 型は増やさず、解釈メソッドを追加した。

いかにもJavaらしい、 後方互換を守る現実解である。



0 件のコメント:

コメントを投稿

【Java進化史 番外編】Java8で「符号なし」が追加?本当か?

【Java進化史 番外編】Java8で「符号なし」が追加?本当か? そういえば。 Java8で「符号なし」が導入された、と どこかで聞いたことがある。 ……え? Javaって、unsigned無かったよね? なんで今頃? ちょっと気になったので...