我正在浏览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
所以我欢迎任何关于这个成语的必要性/用法的反馈。
答案 0 :(得分:3)
必要性很简单:左移1生成的常数,例如1 << N
,总是2的幂。
这在定义掩码时很有用,或者在HashMap
情况下,在分配一个2的幂是更好的可优化值的对象(通过缓存和类似的低级别问题)时很有用。
要说清楚一件事,你说:
意味着(至少在我的极简主义情况下)编译器会将后者转换为十进制表示法
这不是事实,存储的值是什么,它本身没有注释。 16
和1<<4
都具有相同的语义值,它们在文本上的表示方式与它没有任何关系。
答案 1 :(得分:3)
它是完全等价的,但它是用这种方式编写的,以便更清楚地显示值的来源以及计算方式 - 在这种情况下,它的目的是2 ^ 4。
它可能是以任何一种方式编写的,作者只是认为这会更加自我记录。