In the previous tutorial that dealt with binary notation, things got a little ornery when we started expressing 32 bit int and 64 bit long data types using binary notation. Aw, who are we kidding – it was ornery just expressing 8-bit and 16-bit byte and short data types. Seriously though, looking at the initializations below, could you quickly conclude how many ones and zeros were in each of those binary numbers?
int overflow = 0b10101010101010101010101010101011; long bow = 0b101010101010101010101010101010111L;
Now, what if I asked the question again, using the following code:
int overflow = 0b1010_1010_1010_1010_1010_1010_1010_1011; long bow = 0b1__01010101__01010101__01010101__01010111L;
Rules for using Numeric Literals with Underscores in Java 7
With the first binary number being broken into quartets by separating every fourth number by an underscore, or with the second binary number being broken up into octets, separate by two underscores, the numbers become much more readable. Declaring numeric literals with underscores interspersed within the digits would have causes a compile error in any previous release of the language, but in Java 7, numeric literals with underscore characters are not only legal, but they're highly encouraged.
Now, there are a four key rules you need to pay attention to when using numeric literals with underscore characters.
- Underscores can't go at the beginning or the end of a number.
- You can't use an underscore on either side of a decimal.
- The underscore cannot go before an identifying suffix such as F, D or L
- You can't put an underscore before or after the binary or hexadecimal identifiers b and x.
Let's take a look at these rules in more detail.
Underscores can't go at the beginning or the end of a number
This attempt at using an underscore at the termination of a number:
int x = 1_;
results in the following compile error:
Underscores have to be located within digits
Interestingly, flipping the underscore to the preceding side of the digit generates a different error message. Take a look at the following line of code:
int x = _1;
This code generates a compiler error that says: _1 cannot be resolved to a variable
You see, when you use a leading underscore, the JVM thinks you're referring to a variable, so it gives you the error that the variable name cannot be resolved. It's as though the compiler is expecting some code that looks like this:
int _1 = 12345; int x = _1;
The bottom line? Don't start or finish a numeric literal with an underscore.
You can't use an underscore on either side of a decimal
So, the following three lines of code would all kill the compiler:
double pious1 = 3_.14; //fail double pious2 = 3._14; //fail double pious3 = 3_._14; //fail
The underscore cannot go before an identifying suffix such as F, D or L
So, all three of the following attempted initializations will fail:
double trouble = 123.456_D; //fail float myBoat = 321.123_F; //fail long winded = 90210_L; //fail
However, with a slight adjustment of the location of the underscore, each of these could be made to work, as follows:
double trouble = 1_23.456D; //valid float myBoat = 321.1_23F; //valid long winded = 902_10L; //valid
You can't put an underscore before or after the binary or hexadecimal identifiers b and x
So the following attempted initializations are not valid:
byte size = 0_b111101; //fail byte me = 0b_111101; //fail int hexed = 0_x_BABE; //fail
But other than that, you're in the clear to intersperse underscores wherever and as often as you see fit. Numeric underscores are a great enhancement to the language, and knowing when and how to use them is going to help you nail a certification question or two if you ever work up the gumption to tackle the Oracle Certified Professional, Java 7 SE Programmer (OCPJP) designation.