Where To Use the Underscore in Java
In this post of our series “Stranger things in Java” - dedicated to Java insights, we will try to clarify the use of the underscore symbol "_" in Java programming.
Join the DZone community and get the full member experience.
Join For FreeThis series of articles called “Stranger things in Java”, is inspired by the contents of my book “Java for Aliens”. These articles are dedicated to insights into the Java language. Deepening the topics we use every day will allow us to master Java coding even in the strangest scenario.
In this article, we will try to clarify the use of the underscore symbol "_
" in Java programming. So, let's examine the use cases of this symbol within a Java program. Let's start with the best-known case.
Underscore and Identifiers
We know that it is possible to use the underscore symbol as part of an identifier of a programming element. In fact, to define an identifier in Java, we can use:
- Uppercase and lowercase letters
- Numbers (but not at the beginning of the identifier)
- The dollar sign '$' (which, however, is practically never used)
- The underscore symbol '
_
'
However, the standard conventions for defining the identifiers of variables, methods, Java types (classes, interfaces, enumerations, records, and annotations), packages and modules, do not require the use of the underscore symbol. In Java programming, only the standard convention for constant identifiers requires the use of the underscore symbol. In fact, this convention recommends defining names consisting of uppercase characters only and using the underscore symbol as a word separator to improve readability. For instance:
final int SIDES_NUMBER_OF_SQUARE = 4; final double PI = 3.14;
This is because a constant must be easily recognizable, and by using all capital characters the developer is able to distinguish the constants from the variables at a glance.
New in Java 8
Up to version 8 of Java, it was even possible to use just one underscore symbol as the identifier of a Java programming element, such as a variable or a method. In version 8, however, the compiler already issued a warning in order to not use this practice. In fact, if we tried to define for example a variable like this with Java 8:
int _;
The code compiled correctly, but this warning was printed:
warning: '_' used as an identifier
int _;
^
(use of '_' as an identifier might not be supported in releases after Java SE 8)
1 warning
Which warned us that the use of the underscore symbol as an identifier may no longer be supported in future versions.
New in Java 9
In fact, if we try to compile the previous code with a version higher than 8, we will directly get the following compilation error:
error: as of release 9, '_
' is a keyword, and may not be used as an identifier
error: as of release 9, '_' is a keyword, and may not be used as an identifier
int _;
^
1 error
This warns us that since version 9 it is no longer possible to use a single underscore as an identifier.
Note that in this compiler message the underscore is defined as a keyword, which is not entirely correct. A keyword in Java has a very specific meaning, such as class, while, or instanceof. It would be more appropriate to define underscore as a reserved word, that is a word that has no particular meaning for Java syntax, but which cannot be used as a method identifier. The other reserved words defined by the language are goto and const, which actually have no meaning for Java syntax, but are not accepted by the compiler as identifiers.
However, it is possible to use two or more consecutive underscores as an identifier without any problems. In fact, the following declaration is compiled without errors:
int __;
Underscore for Integer Types
From version 8 of Java, to improve the readability of the values assigned to our numeric variables, it is also possible to use underscores. For example, the following statement
int i = 1000000000;
Can be rewritten as follows:
int i = 1_000_000_000;
Making it clear that the value of the variable i
is worth one billion.
Underscore can also be used to improve the readability of numeric types written with other notations. For example, the following declaration using binary notation marked with the prefix 0b
(or 0B
):
int bytes = 0b10100001010001011010000101000101
Can be rewritten by separating the various bytes with underscores:
int bytes = 0b10100001_01000101_10100001_01000101
It is clear that the use of underscore guarantees greater readability of our numerical values.
Other Notations for Integer Types
We can also represent an integer in hexadecimal format marked by the prefix 0x
(or 0X
):
long maxLong = 0x7fff_ffff_ffff_ffffL;
Or even an integer in octal format, for example separating the prefix 0
that characterizes this notation from the octal number, which often confuses the ideas of the developer. Indeed:
int octal = 052;
It is actually an octal number which when converted as a decimal number is 42! Rewriting it like this:
int octal = 0_52;
We will be less likely to get confused.
We can theoretically use sequences of multiple adjacent underscores:
int octal = 0__________52;
Underscore for Floating-Point Numeric Types
We can use the underscore symbol also for the floating-point numeric types float
and double
identifiers. For example:
final float PI = 3.14_15F;
Or:
double d = 0.000_000_001;
It is also possible to use exponential or engineering notation characterized by the use of the letter 'e
' (which can be both upper and lower case). For example:
double d = 0.260_174E-2; //equivalent to 0.260174 divided by 100 = 0.00260174
One Rule to Remember
There is only one rule to respect in order to correctly use underscores with numeric data types:
- You can use one or more underscores only between two numbers
For example, the following statements are not valid:
final float PI_1 = 3_.1415F;
final double PI_2 = 3._1415D;
long socialSecurityNumber = 999_99_9999_L;
int x1 = _52;
int x2 = 52_;
int x3 = 0_x52;
int x4 = 0x_52;
int x5 = 0x52_;
Notice that the octal declaration we saw earlier:
int octal = 0_52;
It is valid as the prefix does not contain a character, but only 0
, which is one of the digits that can be used for an octal number (which can use only 8 digits: 0
, 1
, 2
, 3
, 4
, 5
, 6
and 7
).
For the same reason the following statement is valid:
long maxLong = 0x7fff_ffff_ffff_ffffL;
In this case, in fact, f is not to be intended as a character, but is actually one of the possible digits of a hexadecimal number (which can use 16 digits: 0
, 1
, 2
, 3
, 4
, 5
, 6
and 7
, 8
, 9
, a
, b
, c
, d
, e
, f
). In hexadecimal notation f
is equal to 15
.
Conclusion
In this article, we have explored the use cases in which we can use underscore in Java programming. In particular, we have seen that in addition to the convention that requires its use in the declaration of constant identifiers, from Java 8 onwards it is possible to use underscore as a separator of digits (both integers and decimals), to make them easier to interpret.
This practice is more useful when the values to be defined are higher, and it is easy to use since there is only one rule to respect. We have also seen that from Java 9 onwards we can no longer use a single underscore as the identifier of a Java programming element.
Note dell’autore
This article is based on a few paragraphs from chapter 3 of my book "Java for Aliens".
Published at DZone with permission of Claudio De Sio Cesari. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments