The problem you're running into is that your operation breaks down like this:
l |= 0b1 << 37;
Turns into, in sequence:
int _temp = 1 << 37;
l |= (long) _temp;
The reason it's like that is because 0b1
, or any numeric literal that lacks a decimal part and a trailing letter to indicate what kind of literal you want (D/F/L for double/float/long), is therefore an int
, period. You then left-shift this int value (1
; 0b1
is just a weird way to write 1
after all) by 37. The spec of left-shift states that the right-hand operator of a shift operation only considers the lower 5 bits for int shifts and the lower 6 for long shifts. Because otherwise you'd just be making the value 0. Thus, someInt << 37
is a weird way of writing someInt << 5
.
The solution is to make sure that your shift operation is actually happening on longs. There are many, many ways to make that happen.
Use a long literal
By writing a trailing L. It can be written in either case, but style guides and developers will egg your house if you use a lowercase l because duh that is incredibly stupid, don't do that. It looks like a 1. Thus:
l |= 1L << 37; // or if you must, 0b1L works too
One step at a time.
long temp = 1;
temp <<= 37;
l |= temp;
Cast it
l |= ((long) 0b1) << 37;
These will all get the job done: They all end up having the <<
operation be in 'long mode' (which occurs if the LHS is of type long, which it is, in all these 3 examples).