Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining Java Constants using Bit-Shift Notation

I was going through the source code of the java.util.HashMap class and noticed that the explicit no-arg constructor expects two constants:

/**
 * 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);
}

But when I looked at the DEFAULT_INITIAL_CAPACITY constant, I found that it was defined as follows:

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

I've never seen this type of construct used in any product I've worked on, and couldn't find any results in the Java Language Specification or through Googling. So I looked at the byte code, but I found that using 16 vs 1 << 4 provided identical output, meaning that (at least in my minimalist case) the compiler will convert the latter to decimal notation. The bytecode of both versions includes the definition:

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

So I would welcome any feedback on the necessity/use of this idiom.

like image 713
Kon Avatar asked Jan 04 '15 01:01

Kon


2 Answers

It's fully equivalent, but it was written this way to make it clearer where the value came from and how it was computed -- in this case that it was intended to be 2^4.

It could have been written either way, the authors just thought this would be more self-documenting.

like image 168
Louis Wasserman Avatar answered Sep 30 '22 15:09

Louis Wasserman


The necessity is simple: a constant generated with a left shift of 1, eg 1 << N will always be a power of two.

This is useful when defining masks or, in the HashMap situation, when allocating an amount of objects for which a power of two is a better optimizable value (by caching and similar low level issues).

Just to clear a thing, you say:

meaning that (at least in my minimalist case) the compiler will convert the latter to decimal notation

This is not the fact, what matter is the value stored, which doesn't have a notation per se. Both 16 and 1<<4 have the same semantic value, how they are represented textually nothing has to do with it.

like image 35
Jack Avatar answered Sep 30 '22 15:09

Jack