新聞中心
一、前言介紹
無(wú)論在面試過(guò)程中還是平時(shí)的技術(shù)交流中,似乎有很多小伙伴始終記不住java中byte類(lèi)型的取值范圍是多少。究其原因大部分程序員對(duì)這個(gè)取值范圍是不在意的,因?yàn)橹琅c不知道都不影響你完成工作。另外這種知識(shí)點(diǎn)壓根不是讓你死記硬背的,當(dāng)然如果你是從其他文科專(zhuān)業(yè)轉(zhuǎn)過(guò)來(lái)學(xué)編程開(kāi)發(fā)的,還情有可原。但對(duì)一個(gè)理科生來(lái)說(shuō),就不太應(yīng)該了。

在蘭考等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專(zhuān)注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作定制制作,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計(jì),全網(wǎng)營(yíng)銷(xiāo)推廣,外貿(mào)營(yíng)銷(xiāo)網(wǎng)站建設(shè),蘭考網(wǎng)站建設(shè)費(fèi)用合理。
二、取值范圍計(jì)算
在java中,byte占1個(gè)字節(jié),8比特位,可以想象成8個(gè)小塊的數(shù)據(jù)區(qū)間,首位用0、1代表符號(hào)位。**0[正]、1[負(fù)]**,那么繪制出一個(gè)表格如下;
byte 序號(hào) 8 7 6 5 4 3 2 1 2? 2^7 2^6 2^5 2^4 2^3 2^2 2^1 2^0 值 128 64 32 16 8 4 2 1 +127 0 1 1 1 1 1 1 1 -128 1 0 0 0 0 0 0 0
+127 二進(jìn)制求和
2^0+2^1+2^2+2^3+2^4+2^5+2^6+2^7
= 2^(n+1) - 1
= 127
-128 二進(jìn)制求和
2^8
= 128
好了,現(xiàn)在看懂邏輯就很清晰了,為什么是負(fù)數(shù)到-128,因?yàn)?代表負(fù)數(shù)的符號(hào)位,也就整整好好是2的8次方,-128。
三、進(jìn)制數(shù)值轉(zhuǎn)換
因?yàn)閖ava語(yǔ)言與一些其他語(yǔ)言byte的取值范圍不同,所以在有時(shí)候處理一些文件時(shí)候需要進(jìn)行進(jìn)制轉(zhuǎn)換。也就是 -128~127 與 0~255 的轉(zhuǎn)換處理;
比如我們現(xiàn)在將一個(gè)java中byte=120,轉(zhuǎn)換成 0~255取值范圍的數(shù)值;
一般可以進(jìn)行與運(yùn)算;
120 & 0x0FF
同時(shí)還可以進(jìn)行增位運(yùn)算;(也就是將8個(gè)字節(jié)長(zhǎng)度的內(nèi)容,放到16個(gè)長(zhǎng)度中,進(jìn)行轉(zhuǎn)換)
byte[] val = {-120};
BigInteger bigInteger = new BigInteger(1, val);
//有符號(hào)
System.out.println(bigInteger.byteValue());
//無(wú)符號(hào)(增位)
String str_hex = bigInteger.toString(16);
System.out.println(Integer.parseInt(str_hex, 16)); // 136
四、解析一段class字節(jié)碼
java的類(lèi)文件都會(huì)被編譯成class文件,那么class文件需要經(jīng)過(guò)jvm的解析、驗(yàn)證,加載等處理才可以被虛擬機(jī)的指令執(zhí)行操作。
如果下是一段class文件的byte數(shù)組,將內(nèi)容解析出對(duì)應(yīng)的結(jié)果;
public class ClassReaderTest {
//取部分字節(jié)碼:java.lang.String
private static byte[] classData = {
-54, -2, -70, -66, 0, 0, 0, 52, 2, 26, 3, 0, 0, -40, 0, 3, 0, 0, -37, -1, 3, 0, 0, -33, -1, 3, 0, 1, 0, 0, 8, 0,
59, 8, 0, 83, 8, 0, 86, 8, 0, 87, 8, 0, 110, 8, 0, -83, 8, 0, -77, 8, 0, -49, 8, 0, -47, 1, 0, 3, 40, 41, 73, 1,
0, 20, 40, 41, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 59, 1, 0, 20, 40, 41,
76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 1, 0, 3, 40, 41, 86, 1, 0, 3,
40, 41, 90, 1, 0, 4, 40, 41, 91, 66, 1, 0, 4, 40, 41, 91, 67, 1, 0, 4, 40, 67, 41, 67, 1, 0, 21, 40, 68, 41, 76,
106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 1, 0, 4, 40, 73, 41, 67, 1, 0, 4};
public static void main(String[] args) {
//classData是我們的字節(jié)碼,第一是-54,因?yàn)閎yte取值范圍是-128~+127,所以如果想看到和其他虛擬機(jī)一樣的值,需要進(jìn)行與運(yùn)算。
System.out.println("* byte字節(jié)碼與運(yùn)算原值(-54)換行后(-54 & 0x0FF):" + (-54 & 0x0FF));
//校驗(yàn)?zāi)?shù)
readAndCheckMagic();
//校驗(yàn)版本號(hào)
readAndCheckVersion();
//接下來(lái)會(huì)依次讀取[可以參照java版本虛擬機(jī)代碼];constantPool、accessFlags、thisClassIdx、supperClassIdx、interfaces、fields、methods、attributes
}
/**
* 校驗(yàn)?zāi)?shù)
*
* 很多文件格式都會(huì)規(guī)定滿足該格式的文件必須以某幾個(gè)固定字節(jié)開(kāi)頭,這幾個(gè)字節(jié)主要起到標(biāo)識(shí)作用,叫作魔數(shù)(magic number)。
* 例如;
* PDF文件以4字節(jié)“%PDF”(0x25、0x50、0x44、0x46)開(kāi)頭,
* ZIP文件以2字節(jié)“PK”(0x50、0x4B)開(kāi)頭
* class文件以4字節(jié)“0xCAFEBABE”開(kāi)頭
*/
private static void readAndCheckMagic() {
System.out.println("\r\n------------ 校驗(yàn)?zāi)?shù) ------------");
//從class字節(jié)碼中讀取前四位
byte[] magic_byte = new byte[4];
System.arraycopy(classData, 0, magic_byte, 0, 4);
//將4位byte字節(jié)轉(zhuǎn)成16進(jìn)制字符串
String magic_hex_str = new BigInteger(1, magic_byte).toString(16);
System.out.println("magic_hex_str:" + magic_hex_str);
//byte_magic_str 是16進(jìn)制的字符串,cafebabe,因?yàn)閖ava中沒(méi)有無(wú)符號(hào)整型,所以如果想要無(wú)符號(hào)只能放到更高位中
long magic_unsigned_int32 = Long.parseLong(magic_hex_str, 16);
System.out.println("magic_unsigned_int32:" + magic_unsigned_int32);
//魔數(shù)比對(duì),一種通過(guò)字符串比對(duì),另外一種使用假設(shè)的無(wú)符號(hào)16進(jìn)制比較。如果使用無(wú)符號(hào)比較需要將0xCAFEBABE & 0x0FFFFFFFFL與運(yùn)算
System.out.println("0xCAFEBABE & 0x0FFFFFFFFL:" + (0xCAFEBABE & 0x0FFFFFFFFL));
if (magic_unsigned_int32 == (0xCAFEBABE & 0x0FFFFFFFFL)) {
System.out.println("class字節(jié)碼魔數(shù)無(wú)符號(hào)16進(jìn)制數(shù)值一致校驗(yàn)通過(guò)");
} else {
System.out.println("class字節(jié)碼魔數(shù)無(wú)符號(hào)16進(jìn)制數(shù)值一致校驗(yàn)拒絕");
}
}
/**
* 校驗(yàn)版本號(hào)
*
* 魔數(shù)之后是class文件的次版本號(hào)和主版本號(hào),都是u2類(lèi)型。假設(shè)某class文件的主版本號(hào)是M,次版本號(hào)是m,那么完整的版本號(hào)可以
* 表示成“M.m”的形式。次版本號(hào)只在J2SE 1.2之前用過(guò),從1.2開(kāi)始基本上就沒(méi)有什么用了(都是0)。主版本號(hào)在J2SE 1.2之前是45,
* 從1.2開(kāi)始,每次有大版本的Java版本發(fā)布,都會(huì)加1{45、46、47、48、49、50、51、52}
*/
private static void readAndCheckVersion() {
System.out.println("\r\n------------ 校驗(yàn)版本號(hào) ------------");
//從class字節(jié)碼第4位開(kāi)始讀取,讀取2位
byte[] minor_byte = new byte[2];
System.arraycopy(classData, 4, minor_byte, 0, 2);
//將2位byte字節(jié)轉(zhuǎn)成16進(jìn)制字符串
String minor_hex_str = new BigInteger(1, minor_byte).toString(16);
System.out.println("minor_hex_str:" + minor_hex_str);
//minor_unsigned_int32 轉(zhuǎn)成無(wú)符號(hào)16進(jìn)制
int minor_unsigned_int32 = Integer.parseInt(minor_hex_str, 16);
System.out.println("minor_unsigned_int32:" + minor_unsigned_int32);
//從class字節(jié)碼第6位開(kāi)始讀取,讀取2位
byte[] major_byte = new byte[2];
System.arraycopy(classData, 6, major_byte, 0, 2);
//將2位byte字節(jié)轉(zhuǎn)成16進(jìn)制字符串
String major_hex_str = new BigInteger(1, major_byte).toString(16);
System.out.println("major_hex_str:" + major_hex_str);
//major_unsigned_int32 轉(zhuǎn)成無(wú)符號(hào)16進(jìn)制
int major_unsigned_int32 = Integer.parseInt(major_hex_str, 16);
System.out.println("major_unsigned_int32:" + major_unsigned_int32);
System.out.println("版本號(hào):" + major_unsigned_int32 + "." + minor_unsigned_int32);
}
}
測(cè)試結(jié)果:
* byte字節(jié)碼與運(yùn)算原值(-54)換行后(-54 & 0x0FF):202
------------ 校驗(yàn)?zāi)?shù) ------------
magic_hex_str:cafebabe
magic_unsigned_int32:3405691582
0xCAFEBABE & 0x0FFFFFFFFL:3405691582
class字節(jié)碼魔數(shù)無(wú)符號(hào)16進(jìn)制數(shù)值一致校驗(yàn)通過(guò)
------------ 校驗(yàn)版本號(hào) ------------
minor_hex_str:0
minor_unsigned_int32:0
major_hex_str:34
major_unsigned_int32:52
版本號(hào):52.0
Process finished with exit code 0
五、綜上總結(jié)
- 關(guān)于byte在文章;《用java實(shí)現(xiàn)jvm虛擬機(jī)》中講過(guò),但是沒(méi)有單獨(dú)拿出來(lái)分析,現(xiàn)在單獨(dú)分析下也增強(qiáng)記憶。
- 任何一個(gè)可能不起眼的知識(shí)點(diǎn),不是他不重要,而是你還沒(méi)有用到。就像有句話說(shuō),不是讀書(shū)沒(méi)用,而是你沒(méi)用。國(guó)語(yǔ)博大精深!
- 認(rèn)認(rèn)真真對(duì)待每一個(gè)知識(shí)點(diǎn),不斷的夯實(shí)自己的地基,這就像是蓋房子在打地基一樣。越深越穩(wěn),最終所服能于你的上層架構(gòu)才會(huì)更加精進(jìn)。?
當(dāng)前題目:似乎你總也記不住,byte取值范圍是-127~128還是-128~127
地址分享:http://www.5511xx.com/article/dhhscpe.html


咨詢
建站咨詢
