## Java專題六:運算符
[TOC]
### 6.1.位運算符&
> 2個操作數轉換成二進制后,**相同位全為1取1,否則取0**原則。
例:
Java中類(Class)、方法(Method)、成員(Member)都有修飾符(Modifier),為了確定它們包含其中一種或多種修飾符,使用到了按位與&操作。
```
// java.lang.reflect.Modifier
public class Modifier {
public static final int PUBLIC = 0x00000001;
public static final int PRIVATE = 0x00000002;
public static final int PROTECTED = 0x00000004;
public static final int STATIC = 0x00000008;
public static final int FINAL = 0x00000010;
public static final int SYNCHRONIZED = 0x00000020;
public static final int VOLATILE = 0x00000040;
public static final int TRANSIENT = 0x00000080;
public static final int NATIVE = 0x00000100;
public static final int INTERFACE = 0x00000200;
public static final int ABSTRACT = 0x00000400;
public static final int STRICT = 0x00000800;
public static boolean isPublic(int mod) {
return (mod & PUBLIC) != 0;
}
// ...
}
```
從Modifier類中可以看出各種修飾符常量值之間按位與的結果都為0,如`PUBLIC`和`PRIVATE`轉換成二進制分別為0000 0001和0000 0010,根據按位與原則,`PUBLIC`&`PRIVATE`結果為0,
因此判斷Java類、方法、成員是否包含某種類,可通過mod(修飾符集合)與各種修飾符常量按位與操作判斷,如上面的判斷是否是Public通過`(mod & PUBLIC) != 0`實現。
通常先定義用到的兩兩按位與&結果為0的常量,然后通過常量集合值與待判斷的常量值進行按位與操作結果是否為0判斷該常量值是否存在于常量集合中。
### 6.2.位運算符^
> 2個操作數轉換成二進制后,**相同位相同取0,相反取1**原則。
```
// java.util.HashMap
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
```
h=1110 1101 1010 0111 1110 0101 1110 0101
?
h >>> 16 = 0000 0000 0000 0000 1110 1101 1010 0111
(h = key.hashCode()) ^ (h >>> 16) = 1110 1101 1010 0111 0000 1000 0100 0010
運算符>>>參考本節第5點,h >>> 16后2個key的hash值可能會變成一樣的,因此在右移運算符后增加了^異或運算符,保證誤將不同hash值的key識別成同一key的問題。
### 6.3.位運算符>>
> 又稱有符號右移運算符,X>>m 首先將待操作數X轉換成二進制,然后**右移動指定的位數m,如果是正數,高位補0,如果是負數,高位補1**,結果相當于X/(2的m次方)
例:
```
// java.util.ArrayList
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
```
在ArrayList中動態擴容時可以看到`int newCapacity = oldCapacity + (oldCapacity >> 1);`,實際上是將新容量擴充為原來的1.5倍。
### 6.4.位運算符<<
> 又稱左移移運算符,X<<m 首先將待操作數X轉換成二進制,然后**左移動指定的位數m,低位補0**,結果相當于X*(2的m次方)
例:
16<<2 16的二進制0001 0000,向左移動2位,低位補0,變成0100 0000,轉換成十進制為64,等于16*(2的2次方)
### 6.5.位運算符>>>
> 又稱無符號右移移運算符,X>>>m 首先將待操作數X轉換成二進制,然后**右移動指定的位數m,高位補0**,結果相當于X/(2的m次方)
例:
16>>>2 16的二進制0001 0000,向右移動2位,低位補0,變成0000 0100,轉換成十進制為4,等于16/(2的2次方)
- JavaCook
- Java專題零:類的繼承
- Java專題一:數據類型
- Java專題二:相等與比較
- Java專題三:集合
- Java專題四:異常
- Java專題五:遍歷與迭代
- Java專題六:運算符
- Java專題七:正則表達式
- Java專題八:泛型
- Java專題九:反射
- Java專題九(1):反射
- Java專題九(2):動態代理
- Java專題十:日期與時間
- Java專題十一:IO與NIO
- Java專題十一(1):IO
- Java專題十一(2):NIO
- Java專題十二:網絡
- Java專題十三:并發編程
- Java專題十三(1):線程與線程池
- Java專題十三(2):線程安全與同步
- Java專題十三(3):內存模型、volatile、ThreadLocal
- Java專題十四:JDBC
- Java專題十五:日志
- Java專題十六:定時任務
- Java專題十七:JavaMail
- Java專題十八:注解
- Java專題十九:淺拷貝與深拷貝
- Java專題二十:設計模式
- Java專題二十一:序列化與反序列化
- 附加專題一:MySQL
- MySQL專題零:簡介
- MySQL專題一:安裝與連接
- MySQL專題二:DDL與DML語法
- MySQL專題三:工作原理
- MySQL專題四:InnoDB存儲引擎
- MySQL專題五:sql優化
- MySQL專題六:數據類型
- 附加專題二:Mybatis
- Mybatis專題零:簡介
- Mybatis專題一:配置文件
- Mybatis專題二:映射文件
- Mybatis專題三:動態SQL
- Mybatis專題四:源碼解析
- 附加專題三:Web編程
- Web專題零:HTTP協議
- Web專題一:Servlet
- Web專題二:Cookie與Session
- 附加專題四:Redis
- Redis專題一:數據類型
- Redis專題二:事務
- Redis專題三:key的過期
- Redis專題四:消息隊列
- Redis專題五:持久化