問題由來
在閱讀google的開源項目zxing時,遇到以下代碼:
public final String toString() {
byte[] row = new byte[width];
StringBuilder result = new StringBuilder(height * (width + 1));
for (int y = 0; y < height; y++) {
row = getRow(y, row);
for (int x = 0; x < width; x++) {
int luminance = row[x] & 0xFF;
char c;
if (luminance < 0x40) {
c = '#';
} else if (luminance < 0x80) {
c = '+';
} else if (luminance < 0xC0) {
c = '.';
} else {
c = ' ';
}
result.append(c);
}
result.append('\n');
}
return result.toString();
}
閱讀到上述源代碼時,對于int luminance = row[x] & 0xFF;最初不是很理解。查詢之后,發(fā)現(xiàn)原來Java中是沒有unsigned byte type的。也就是說Java中所有的byte類型都是signed類型。只能表達(dá)(-128127).而此處的代碼為了讀取像素值,所需要的值是(0255),所以需要的是unsigned byte而不是signed byte。但是Java中所有的byte都是signed byte。那怎么處理呢?
Java中unsigned byte 的轉(zhuǎn)換
正如上述我們看到的代碼所示:
int luminance = row[x] & 0xFF;
首先widening類型。將byte聲明為short或者int類型。然后與0xFF取&即可。
下面,具體說明這樣做的原理。
0xff 表示為二進(jìn)制就是 1111 1111。在signed byte類型中,代表-1;但在short或者int類型中則代表255.
當(dāng)把byte類型的-1賦值到short或者int類型時,雖然值仍然代表-1,但卻由1111 1111變成1111 1111 1111 1111.
再將其與0xff進(jìn)行掩碼:
-1: 11111111 1111111
0xFF: 00000000 1111111
255: 00000000 1111111
所以這樣,-1就轉(zhuǎn)換成255.
測試程序
我們寫了一個簡單的程序?qū)ζ溥M(jìn)行Java unsigned byte 類型轉(zhuǎn)換的測試:
for (byte b = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++) { short s = b; s &= 0xff; System.out.println(b + " & 0xFF = " + s); }
將所有的byte值進(jìn)行循環(huán)轉(zhuǎn)換,輸出結(jié)果如下:
-128 & 0xFF = 128 -127 & 0xFF = 129 .... -2 & 0xFF = 254 -1 & 0xFF = 255 0 & 0xFF = 0 1 & 0xFF = 1 ... 125 & 0xFF = 125 126 & 0xFF = 126
小結(jié)
Java的unsigned byte 類型轉(zhuǎn)換屬于一個細(xì)節(jié)問題,由于java中沒有內(nèi)置unsigned byte類型,所以當(dāng)我們需要使用其時,需要對signed byte 類型進(jìn)行轉(zhuǎn)換。而這種轉(zhuǎn)換是比較簡單的,首先將其擴大類型到short或者int,然后對0xff進(jìn)行掩碼即可。
備注
2016.7.5閱讀zxing源碼時的小問題