The compiler knows how to treat the final result of an expression, but the individual literals (or variables) in an expression each have their own types, as do the intermediate values in the expression. For example:
static final double HALF = 1 / 2;
will actually have the value zero, because the literal 1 and 2 are int
-typed, the division is an integer division that produces an int
value of zero, and then Java turns that into a double
. In contrast, in the expression
static final double HALF = 1d / 2;
the compiler knows to treat the first value as a double
. The second value is promoted, Java does floating-point division, and the result is 0.5
as expected.
There are other situations, like autoboxing, where the compiler may treat equivalent values differently depending on their types; when passed to a method that takes an Object
, 0
is an Integer
, while 0L
is a Long
. This sort of situation occurs frequently in persistence/DAO code. Also, when compiling, the compiler evaluates compile-time constant expressions and puts their values directly into the code. The values of float
and double
expressions may be different because of the differing precisions of the types, and so you need to specify if you want a floating-point expression treated as just a float
instead of as a double
(the default).