首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 位移運算符詳解:<<、>>、>>> 的原理、規則與實戰應用

     編輯:Java 相關知識

位移運算符是 Java 基礎中高頻考點、也是底層優化、加解密、網絡協議解析的常用工具。本文系統講解 `<<`(左移)、`>>`(有符號右移)、`>>>`(無符號右移)的二進制規則、正負數行為差異、等價數學運算、常見陷阱與實戰應用場景。

一、三大位移運算符規則總覽

運算符名稱規則符號位處理等價數學運算
<<有符號左移二進制整體左移 n 位,低位補 0保持符號位參與移動(可能改變符號)x * 2^n(無溢出時)
>>有符號右移二進制整體右移 n 位,高位補符號位補符號位(正補 0,負補 1)x / 2^n(向零取整)
>>>無符號右移二進制整體右移 n 位,高位補 0忽略符號,高位固定補 0無簡單等價(視為無符號整數除法)

二、詳細規則與代碼驗證

1. << 左移

int x = 10;          // 0000 0000 0000 0000 0000 0000 0000 1010
int x2 = x << 2;     // 0000 0000 0000 0000 0000 0000 0010 1000 = 40
// 10 * 2^2 = 40

// 負數左移
int y = -10;         // 1111 1111 1111 1111 1111 1111 1111 0110 (補碼)
int y2 = y << 2;     // 1111 1111 1111 1111 1111 1111 1101 1000 = -40
// 負數左移 n 位 ≈ -( |x| * 2^n ),但可能溢出改變符號

2. >> 有符號右移(算術右移)

int x = 10;          // 0000...1010
int x2 = x >> 2;     // 0000...0010 = 2  (10 / 4 = 2.5 -> 2)

// 負數右移
int y = -10;         // 1111...0110
int y2 = y >> 2;     // 1111...1101 = -3
// 規律:偶數負數 /2^n 向零取整;奇數負數 /2^n 向零取整再 -1
// -10 / 4 = -2.5 -> 向零取整 -2 -> 但結果是 -3(因補碼特性)
// 通用公式:x >> n 等價於 floor(x / 2^n) 對負數向下取整

3. >>> 無符號右移(邏輯右移)

int x = 10;          
int x2 = x >>> 2;    // 同 >>,結果 2

int y = -10;          // 1111...0110 (32 位)
int y2 = y >>> 2;    // 0011...1101 = 1073741821
// 高位補 0,負數變大正數!此操作視 int 為無符號 32 位整數

三、移位位數模 32 / 64 特性

Java 規定:int 移位位數取模 32,long 取模 64。

10 << 34  ==  10 << (34 % 32)  ==  10 << 2  == 40
10 >> 34  ==  10 >> 2  == 2
-10 >>> 34 == -10 >>> 2 == 1073741821

四、實戰應用場景

1. 高效乘除 2 的冪次

int pageSize = 1 << 10;      // 1024,替代 1024
int index = offset >> 10;    // offset / 1024
int remainder = offset & 1023; // offset % 1024 (位與操作)

2. 顏色分量提取 (ARGB)

int argb = 0xFFCC9966;
int a = (argb >> 24) & 0xFF;  // 255
int r = (argb >> 16) & 0xFF;  // 204
int g = (argb >> 8)  & 0xFF;  // 153
int b = argb & 0xFF;          // 102

3. 權限掩碼 / 標誌位操作

int READ    = 1 << 0;  // 0001
int WRITE   = 1 << 1;  // 0010
int EXECUTE = 1 << 2;  // 0100

int perm = READ | WRITE;      // 0011 = 3
boolean canRead  = (perm & READ) != 0;
perm |= EXECUTE;              // 添加執行權限
perm &= ~WRITE;               // 移除寫入權限

4. 中間值計算避免溢出

int mid = (low + high) >>> 1;  // 無符號右移等價於 (low+high)/2 但不溢出
// 或
int mid = low + ((high - low) >> 1);

5. ReadWriteLock 狀態位分離(源碼應用)

// 狀態高 16 位存讀計數,低 16 位存寫計數
static final int SHARED_SHIFT = 16;
int readCount  = state >>> SHARED_SHIFT;   // 無符號右移取高位
int writeCount = state & 0xFFFF;           // 位與取低位
// 讀鎖獲取:state + (1 << 16)
// 寫鎖獲取:state + 1

五、常見陷阱與最佳實踐

陷阱說明正確做法
負數右移期望正數-10 >> 1 == -5,非 5需正數用 >>> 或先取絕對值
左移溢出改變符號1 << 31 == -2147483648用 long 或 BigInteger 避免溢出
byte/short 自動提升byte b = 1; b << 1 先提升為 int 再移位結果需強轉 (byte)(b << 1)
移位位數為負編譯錯誤確保位數 >= 0
混淆 >> 和 >>>負數行為截然不同記住:>> 保符號,>>> 不保符號

六、總結

  • <<:乘 2^n,低位補 0,可能溢出改符號。
  • >>:除 2^n(算術右移),高位補符號位,負數向下取整。
  • >>>:邏輯右移,高位補 0,負數變大正數,視為無符號數。
  • 移位位數自動模 32/64。
  • 實戰廣泛用於:位標誌、顏色處理、分頁計算、並發狀態壓縮、網絡協議編解碼。

熟練掌握位移運算,能寫出更高效、更底層的 Java 代碼,也是面試必考核心知識點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved