我一直在使用C ++和Java,在这两种语言中,我经常遇到一种奇怪的变量赋值方式,使用按位运算符。使用赋值运算符而不是使用赋值运算符的简单赋值,使用诸如左移的位运算符是很复杂的。 例如,在Java的ServerSocketChannel类中,我们看到以下分配:
public static final int OP_READ = 1 << 0;
public static final int OP_WRITE = 1 << 2;
public static final int OP_CONNECT = 1 << 3;
public static final int OP_ACCEPT = 1 << 4;
我试图通过使用&lt;&lt;来了解我们获得了什么?运营商。我们可以进行简单的赋值,将变量分别分配为1,4,8,16,如下所示:
public static final int OP_READ = 1;
public static final int OP_WRITE = 4;
public static final int OP_CONNECT = 8;
public static final int OP_ACCEPT = 16;
在此处使用<<
运算符增加了什么值?
答案 0 :(得分:3)
这是为了清晰/可读(重要时)。
在字节代码级别,OP_ACCEPT = 16
或OP_ACCEPT = 1 << 4
是相同的(通过javap -constants <YourClass>
)
更容易确切地知道这次转移了多少次。通常,当您执行与两个操作相关的不同操作时,这很重要。
示例将是HashMap
(或者我假设HashXXX
结构),其中,至少在java中,总是在下一个2的幂上选择桶。这简化了处理或者可以合理化,因此桶的数量被声明为:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
同时,两个权力无关紧要,变量不是这样声明的:
static final int TREEIFY_THRESHOLD = 8;
static final int MIN_TREEIFY_CAPACITY = 64
考虑如何选择存储区,例如HashMap
通过(n - 1) & hash
,其中n
是存储区的数量(总是2的幂)。默认容量为16(或更好1 << 4
),表示最后4位为零,执行减1将使它们全部为1。因此,以某种方式,1 << 4
HashMap
意味着将最后4位仅考虑在内(直到下一次重新哈希) 。现在想想1 << 28
例如......没有转变,这将是很长的理由。
至少对我来说,对于这种情况,例如or
或and
会更快地理解这些变量。
答案 1 :(得分:-4)
它们是表示状态由几个“是或否”属性定义的事物的最有效方式。 ACL就是一个很好的例子;如果您说4个离散权限(读取,写入,执行,更改策略),最好将其存储在1个字节而不是浪费4 。
当你离开1位时,数字乘以2。
例如取二进制数5 = 0101 左移1次后,它将变为1010,相当于10。