使用位移表示法定义Java常量

时间:2015-01-04 01:36:42

标签: java constants bit-shift jls

我正在浏览java.util.HashMap类的源代码,并注意到显式的no-arg构造函数需要两个常量:

/**
 * Constructs an empty <tt>HashMap</tt> with the default initial capacity
 * (16) and the default load factor (0.75).
 */
public HashMap() {
    this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
}

但是当我查看DEFAULT_INITIAL_CAPACITY常量时,我​​发现它的定义如下:

/**
 * The default initial capacity - MUST be a power of two.
 */
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

我从来没有见过我使用的任何产品中使用的这种类型的构造,并且在Java Language Specification或通过谷歌搜索找不到任何结果。所以我查看了字节代码,但是我发现使用16 vs 1 << 4提供了相同的输出,这意味着(至少在我的极简主义情况下)编译器会将后者转换为十进制表示法。两个版本的字节码包括以下定义:

javap -c -verbose /---/myClass.class
----
public static final int i;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
ConstantValue: int 16

所以我欢迎任何关于这个成语的必要性/用法的反馈。

2 个答案:

答案 0 :(得分:3)

必要性很简单:左移1生成的常数,例如1 << N,总是2的幂。

这在定义掩码时很有用,或者在HashMap情况下,在分配一个2的幂是更好的可优化值的对象(通过缓存和类似的低级别问题)时很有用。

要说清楚一件事,你说:

  

意味着(至少在我的极简主义情况下)编译器会将后者转换为十进制表示法

这不是事实,存储的值是什么,它本身没有注释。 161<<4都具有相同的语义值,它们在文本上的表示方式与它没有任何关系。

答案 1 :(得分:3)

它是完全等价的,但它是用这种方式编写的,以便更清楚地显示值的来源以及计算方式 - 在这种情况下,它的目的是2 ^ 4。

它可能是以任何一种方式编写的,作者只是认为这会更加自我记录。