Tuesday, May 9, 2023

Why use Underscore in Numbers from Java? Underscore in Numeric Literals Example

JDK 1.7 release had introduced several useful features, despite most of them being syntactic sugar, there use can greatly improve readability and code quality. One such feature is the introduction of underscores in numeric literals. From Java 7 onwards you can write a long digit e.g. 10000000000 to a more readable 10_000_000_000 in your Java source code. One of the most important reasons for using an underscore in numeric literal is avoiding subtle mistakes that are hard to figure out by looking at code. It's hard to notice a missing zero or extra zero between 10000000000 and 1000000000, than 10_000_000_000 and 1_000_000_000.

So, if you are dealing with big numbers in Java source code, use underscore in numbers to improve readability.

By the way, there are rules to use underscore in numeric literals, as they are also a valid character in an identifier, you can only use them in between digits, precisely neither at the start of numeric literal nor at the end of numeric literals.

In the next couple of sections, we will learn how to underscore in numeric literal is implemented and rules to use them in numerical literals.

How underscores in numbers are implemented in Java

As I said that it's syntactic sugar, much like how String in switch case is implemented, this is also implemented using the help of a compiler. At compile time, the compiler removes these underscore and put the actual numbers into variable. For example, 10_000_000 will be converted into 10000000 during compile time.

Since CPU has no problem dealing with a long String of digits and it's fun for him, we don't bother about that, it's us, poor humans which have a problem dealing with longer numbers.  This feature is particularly useful for banking and finance domain application, which deals with a large sum of money, credit card number, bank account numbers and other domains, which deals with longer ids.

Though it's strongly discouraged to write sensitive data in Java files and you should never do in production code, life is much easier with an underscore in numbers than before.

Rules to use underscore in numbers in Java

JDK 7 Underscore in Numeric literals
Java programming language has strict set of rules towards the usage of underscore in numeric literals. As stated, you can only use them in between digits. You can not start a number by underscore, or end a number by an underscore. Here are some more places, where you just can not place underscore in numeric literals :

1) At the beginning or end of a number
2) Adjacent to a decimal point in a floating-point literal
3) Prior to an F or L suffix
4) In positions where a string of digits is expected

Here are a couple of examples, which shows some valid and invalid usage of underscore in numeric literals

float pi1 = 3_.1415F;      // Invalid; cannot put underscores adjacent 
                           // (before) to a decimal point
float pi2 = 3._1415F;      // Invalid; cannot put underscores adjacent (after)
                           // to a decimal point
long socialSecurityNumber1  = 999_99_9999_L;  // Invalid; cannot put underscores 
                                              // prior to an L suffix

int a1 = _52;              // This is an identifier, not a numeric literal, 
                           // starts with underscore
int a2 = 5_2;              // OK (decimal literal)
int a3 = 52_;              // Invalid; cannot put underscores at the end of a literal
int a4 = 5_______2;        // OK (decimal literal)

int a5 = 0_x52;            // Invalid; cannot put underscores in the 0x radix prefix
int a6 = 0x_52;            // Invalid; cannot put underscores at the beginning of a number
int a7 = 0x5_2;            // OK (hexadecimal literal)
int a8 = 0x52_;            // Invalid; cannot put underscores at the end of a number

int a9 = 0_52;             // OK (octal literal)
int a10 = 05_2;            // OK (octal literal)
int a11 = 052_;            // Invalid; cannot put underscores at the end of a number

Here are some more examples of using underscores in numeric literals

long creditCardNumber = 6684_5678_9012_3456L;  // Never do it on production code
long socialSecurityNumber = 333_99_9999L;      // Never, Ever do it on production code
float pi =              3.14_15F;
long hexBytes = 0xFF_EC_DE_5E;
long hexWords = 0xCAFE_BABE;
long maxLong = 0x7fff_ffff_ffff_ffffL;
byte nybbles = 0b0010_0101;
long bytes = 0b11010010_01101001_10010100_10010010;

You can see that code is much more readable than without using underscores in numbers. By the way, always use L to denote a long literal in Java. Though it's legal to use small case l, you should never use it with numbers as it looks exactly similar to digit 1. Tell me if you can find out the differences between 12l and 121, I guess not many. How about 12L and 121?

In short, always use underscore in numbers, especially with long numbers to make them more readable. I know this feature is only available from Java 1.7, and it's not widely used yet, but given Java 8 profile, I am expected that Java 8 will be adopted by the community more quickly and widely than Java 7.


Anonymous said...

long creditCardNumber = 6684_5678_9012_3456L;
why have you asked to never use the above on the production code ?? what does that mean??

Anonymous said...

The warning is against hard-coding credit card numbers and social security numbers in production code.

Post a Comment