## 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专题五:持久化