Java has byte, short, int, char and long integral primitive types and Java language specification describes them very well:

The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two’s-complement integers, respectively, and char, whose values are 16-bit unsigned integers representing UTF-16 code units

I found these types mentioned in all java materials that I read but I saw in practice int and long most of the time. The logical question is if we really need all of them. Common sense tells me that I should check from two perspectives: storage usage and operations speed. I need more time to prepare a test for storage usage so I started with operations speed.

I selected the following operations based on how often I saw them in code

  • The multiplicative operators *, /, and % (§15.17)
  • The additive operators + and – (§15.18)
  • The increment operator ++, both prefix (§15.15.1) and postfix (§15.14.2)
  • The decrement operator –, both prefix (§15.15.2) and postfix (§15.14.3)

and I prepared a jmh benchmark:

I did not include all methods in this code excerpt, original code is available on github. I ran this benchmark three times and the results are:

Most of the operations performed similarly except / and % on long type and last
relatively complex expression that included all other operations.
The fact that division operations are more expensive on long type is not such a big surprise as the results of the last expression on byte and short. The same operations done isolated run in similar amount of time and done together take a bit longer. It can be from widening and cast between byte/short and int:

If an integer operator other than a shift operator has at least one operand of type long, then the operation is carried out using 64-bit precision, and the result of the numerical operator is of type long. If the other operand is not long, it is first widened (§5.1.5) to type long by numeric promotion (§5.6).

Otherwise, the operation is carried out using 32-bit precision, and the result of the numerical operator is of type int. If either operand is not an int, it is first widened to type int by numeric promotion.

These results are not enough to jump to a conclusion, let’s see in the next post what the difference from the storage perspective is.

java version “1.8.0_66”
Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)

Image credit: morzaszum, CC0 Public Domain

Your thoughts are welcome

2 replies