位運(yùn)算符和位移運(yùn)算符是底層運(yùn)算符,處理組成整數(shù)的單個(gè)位蝶涩。其實(shí)在 Java 程序里很少使用位運(yùn)算符理朋,除非處理底層操作(例如網(wǎng)絡(luò)編程)絮识。這兩種運(yùn)算符用于測(cè)試和設(shè)定整數(shù)中的單個(gè)標(biāo)志位。若想理解這些運(yùn)算符的行為嗽上,必須先理解二進(jìn)制數(shù)以及用于表示負(fù)整數(shù)的二進(jìn)制補(bǔ)碼方式次舌。
這些運(yùn)算符的操作數(shù)不能是浮點(diǎn)數(shù)、布爾值兽愤、數(shù)組或?qū)ο蟊四睢H绻僮鲾?shù)是布爾值,&浅萧、| 和^ 運(yùn)算符執(zhí)行的是其他運(yùn)算逐沙,在邏輯運(yùn)算符中說(shuō)到過(guò)。
如果位運(yùn)算符的操作數(shù)中有一個(gè)是 long 類(lèi)型洼畅,結(jié)果就是 long 類(lèi)型吩案。除此之外,結(jié)果都是int 類(lèi)型帝簇。如果位移運(yùn)算符左邊的操作數(shù)是 long 類(lèi)型徘郭,結(jié)果為 long 類(lèi)型;否則,結(jié)果是int 類(lèi)型丧肴。位運(yùn)算符和位移運(yùn)算符如下残揉。
按位補(bǔ)碼(~)
位與(&)
位或(|)
位異或(^)
左移(<<)
帶符號(hào)右移(>>)
不帶符號(hào)右移(>>>)
下面分別進(jìn)行說(shuō)明。
按位補(bǔ)碼(~)
一元運(yùn)算符 ~ 是按位補(bǔ)碼運(yùn)算符芋浮,或叫位或運(yùn)算符抱环。它把單個(gè)操作數(shù)的每一位反相,1變成 0途样,0 變成 1江醇。例如:
byte a = 12;? ?//byte是八位濒憋,12的二進(jìn)制寫(xiě)法是? 00001100
byte b = ~a;? ?// ~00001100 即 11110011或十進(jìn)制243,byte類(lèi)型范圍上溢出何暇,結(jié)果為-13
a&~1? //表示一個(gè)數(shù)的最低位一定為0(&下面講)
//~1的值為1111111111111110,再按“與”運(yùn)算凛驮,最低位一定為0裆站。因?yàn)椤皛”運(yùn)算符的優(yōu)先級(jí)比算術(shù)運(yùn)算符、關(guān)系運(yùn)算符黔夭、邏輯運(yùn)算符和其他運(yùn)算符都高宏胯。
位與(&)
這個(gè)運(yùn)算符在兩個(gè)整數(shù)操作數(shù)的每一位上執(zhí)行邏輯與運(yùn)算,合并這兩個(gè)操作數(shù)本姥。只有兩個(gè)操作數(shù)的同一位都為 1 時(shí)肩袍,結(jié)果中對(duì)應(yīng)的位才是 1。例如:
10 & 7? ? // 00001010 & 00000111 ==> 00000010
前面已經(jīng)說(shuō)過(guò)婚惫,如果操作數(shù)是布爾值氛赐,& 是不常使用的邏輯與運(yùn)算符魂爪。
“與運(yùn)算”的特殊用途:
(1)? 清零。如果想將一個(gè)單元清零艰管,即使其全部二進(jìn)制位為0滓侍,只要與一個(gè)各位都為零的數(shù)值相與,結(jié)果為零牲芋。
(2)? 取一個(gè)數(shù)中指定位
方法:找一個(gè)數(shù)撩笆,對(duì)應(yīng)X要取的位,該數(shù)的對(duì)應(yīng)位為1缸浦,其余位為零夕冲,此數(shù)與X進(jìn)行“與運(yùn)算”可以得到X中的指定位。
例:設(shè)X=10101110裂逐,
??? 取X的低4位耘擂,用 X & 0000 1111 = 0000 1110?即可得到;
??? 還可用來(lái)取X的2絮姆、4醉冤、6位。
位或(|)
這個(gè)運(yùn)算符在兩個(gè)整數(shù)操作數(shù)的每一位上執(zhí)行邏輯或運(yùn)算篙悯,合并這兩個(gè)操作數(shù)蚁阳。如果兩個(gè)操作數(shù)的同一位中有一個(gè)或兩個(gè)都是 1,結(jié)果中對(duì)應(yīng)的位是 1;如果兩個(gè)操作數(shù)的同一位都是 0鸽照,結(jié)果中對(duì)應(yīng)的位是 0螺捐。例如:
10 | 7? ? ? // 00001010 | 00000111 ==> 00001111或15
前面已經(jīng)說(shuō)過(guò),如果操作數(shù)是布爾值矮燎,| 是不常使用的邏輯或運(yùn)算符定血。
“或運(yùn)算”特殊作用:
(1)? 常用來(lái)對(duì)一個(gè)數(shù)據(jù)的某些位置1。
方法:找到一個(gè)數(shù)诞外,對(duì)應(yīng)X要置1的位澜沟,該數(shù)的對(duì)應(yīng)位為1,其余位為零峡谊。此數(shù)與X相或可使X中的某些位置1茫虽。
例:將X=10100000的低4位置1 ,用 X?| 0000 1111 = 1010 1111即可得到既们。
位異或(^)
這個(gè)運(yùn)算符在兩個(gè)整數(shù)操作數(shù)的每一位上執(zhí)行邏輯異或運(yùn)算濒析,合并這兩個(gè)操作數(shù)。如果兩個(gè)操作數(shù)的同一位值不同啥纸,結(jié)果中對(duì)應(yīng)的位是 1;如果兩個(gè)操作數(shù)的同一位都是 1 或都是 0号杏,結(jié)果中對(duì)應(yīng)的位是 0。例如:
10 ^ 7? ? ?// 00001010 ^ 00000111 ==> 00001101或13
如果操作數(shù)是布爾值斯棒,^ 是很少使用的邏輯異或運(yùn)算符盾致。
左移(<<)
<< 運(yùn)算符把左側(cè)操作數(shù)的每一位向左移動(dòng)右側(cè)操作數(shù)指定的位數(shù)莹妒。左側(cè)操作數(shù)的高位被丟掉,右邊缺少的位補(bǔ)零绰上。整數(shù)向左移 n 位旨怠,相當(dāng)于乘于 2的n次方。例如:如果左側(cè)操作數(shù)是 long 類(lèi)型蜈块,右側(cè)操作數(shù)應(yīng)該介于 0 和 63 之間鉴腻。
10 << 1? ??// 00001010 << 1 = 00010100 = 20 = 10*2
7 << 3? ??// 00000111 << 3 = 00111000 = 56 = 7*8
-1 << 2? ??// 0xFFFFFFFF << 2 = 0xFFFFFFFC = -4 = -1*4
如果左側(cè)操作數(shù)是 int 類(lèi)型,右側(cè)操作數(shù)應(yīng)該介于 0 和 31 之間百揭。
帶符號(hào)右移(>>)
>> 運(yùn)算符把左側(cè)操作數(shù)的每一位向右移動(dòng)右側(cè)操作數(shù)指定的位數(shù)爽哎。左側(cè)操作符的低位被移除,移入的高位和原來(lái)的最高位一樣器一。也就是說(shuō)课锌,如果左側(cè)操作數(shù)是正數(shù),移入的高位是 0;如果左側(cè)操作數(shù)是負(fù)數(shù)祈秕,移入的高位是 1渺贤。這種技術(shù)叫高位補(bǔ)符號(hào),作用是保留左側(cè)操作數(shù)的符號(hào)请毛。例如:
10 >> 1? ??// 00001010 >> 1 = 00000101 = 5 = 10/2
27 >> 3? ??// 00011011 >> 3 = 00000011 = 3 = 27/8
-50 >> 2? ??// 11001110 >> 2 = 11110011 = -13 != -50/4
如果左側(cè)操作數(shù)是正數(shù)志鞍,右側(cè)操作數(shù)是 n,>> 運(yùn)算符的計(jì)算結(jié)果相當(dāng)于整數(shù)除以 2的n次方方仿。
不帶符號(hào)右移(>>>)
這個(gè)運(yùn)算符和 >> 類(lèi)似固棚,但是不管左側(cè)操作數(shù)的符號(hào)是什么,高位總是移入 0仙蚜。這種技術(shù)叫高位補(bǔ)零此洲。左側(cè)操作數(shù)是無(wú)符號(hào)的數(shù)字時(shí)才適用這個(gè)運(yùn)算符(可是 Java 的整數(shù)類(lèi)型都帶符號(hào))。下面是一些例子:
0xff >>> 4? ? ?// 11111111 >>> 4 = 00001111 = 15 = 255/16
-50 >>> 2? ? ?// 0xFFFFFFCE >>> 2 = 0x3FFFFFF3 = 1073741811