Some int variables in java.awt.Event class is set by bitwise. Like below:
/**
* This flag indicates that the Shift key was down when the ev
If you look at its binary form, it makes more sense:
1 << 0 : 00000001
1 << 1 : 00000010
1 << 2 : 00000100
1 << 3 : 00001000
Such kind of bit map usually allow you to pass more than 1 value at the same time (as some kind of modifier).
Therefore, you may see something like:
// modifiers is a single int
if ((modifiers & SHIFT_MASK) != 0) {
// shift pressed
}
if ((modifiers & CTRL_MASK) != 0) {
// ctrl pressed
}....
(which you cannot do if you defined them as 1,2,3,4)
You can think of it being passing a set of bits. Such mask to determine whether a specific bit is "ON", or to turn on/off a specific bit without affecting other bits
The example is easy, let's say that the control and shift key are depressed. Using the above, this would make the bitstring something like this:
...11
To make it concrete, let's use an 8 bit string, say something like this:
0111 0011
This would represent that several keys may have been depressed, but perhaps you are only interested in the shift and control keys. If you want to know when both the shift and control key are depressed you can create a new combination:
CTRL_AND_SHIFT_MASK = SHIFT_MASK | CTR_MASK;
Then you can do a bitwise and to determine whether or not the returned bit string has both the control and shift keys depressed:
final boolean isCtrlAndShift = (CTRL_AND_SHIFT_MASK & val) == CTRL_AND_SHIFT_MASK;
By doing a bitwise and, if the two bits for CTRL and SHIFT aren't both 1, then and'ing will result in one of the two bits becoming 0. All other bits will be 0 regardless (since they are 0 in CTRL_AND_SHIFT_MASK
). So if you and
it with your value val
then it should give back your CTRL_AND_SHIFT_MASK
otherwise only one or neither is depressed.
Because those values aren't increasing by one. They are powers of two and used for testing with bitwise-or, exclusive-or, binary-and, etc.
int[] arr = { 1 << 0, 1 << 1, 1 << 2, 1 << 3 };
System.out.println(Arrays.toString(arr));
Output is
[1, 2, 4, 8]
It's a way of writing 2n where n
is the number to the right of the <<
.
Why do this? As pointed out in the other answers, the values are powers of two and you are thereby setting a bit. Suppose you wanted to test for a combination of conditions.
You could then combine bits like for example,
SOME_COMBO_CONDITION = SHIFT_MASK | ALT_MASK
and then test for that condition by testing if both bits are set by doing
current_condition & SOME_COMBO_CONDITION
Using integer codes you'd have to test using a more complex conditional.
I don't know if another answer is needed here but I don't think any really explained why you'd want to do this.
As for the reason for this syntax, they are implementing it as a bitfield. A bitfield is a way to store a bunch of booleans in a single place in memory. This used to be quite common and still can be useful. An object that has 60 booleans (aside from being an inherently bad design) would take 60x4 bytes to store, bit-packing could put all 60 booleans into a single long (with 4 bits to spare). If you had 1 million instances of this object then packing your bits means the difference between needing 8MB of storage (1 million 8-byte longs) and needing 240MB of storage (1 million x 60 booleans each taking 4 bytes).
These days you should almost never use bitfields--we don't usually have an issue with memory and there are better structures available. When you start combining data into bitfields operations actually get significantly slower (which is why java uses an entire 32bit int to store each boolean instead of packing them for you).
By the way, it is still important to know about packed data structures because data over the internet often gets packed and someone has to write code to unpack it (Had to write an mp4 header decoder once, what a mess)
Another interesting question, why say "1 << 0" and "1 << 4" instead of just saying "1" and "16". This is a really good thing to look at. When laid out those constants are extremely readable--one bit in the first position, one bit in the fifth position. You know exactly what position the bit is in by just glancing at it. The second easiest way to specify the bit is hex, if you are good you'd know right of that 0x0400 was 0000010000000000. The worst would be decimal because unless you're a savant or just work with computers a lot you wouldn't know know which bit position was 1024 or 32768, and a constant with 2 bits set would be insanely difficult.
Coding in a way that matches your intention and is easily understandable in a language another human would find most natural is a FANTASTIC habit. Where I usually use it these days is in code like:
public final long SHORT_DELAY = 8000
public final long LONG_DELAY = 85808000
Is that 8000 seconds, 8000 days? Also when the number gets really long it's hard to parse.
I prefer:
public final long sec= 1000
public final long min=sec * 60
public final long hour=min * 60
public final long SHORT_DELAY = 8 * sec
public final long LONG_DELAY = 2 * hour + 23 * min + 8 * sec
This is just a matter of coding in a way that will be clear to your reader, and the code you referenced was a fantastic example of this, so if that's the "Coding style" you meant it is fantastic and is absolutely still relevant.