
We using binary operators, be aware that some of the operands may be promoted to a wider type, to match the type of the other operand. For example in the expression 'a' == 42
, the 'a'
will be promoted to an int
before the comparison is carried out.
When using binary operators with operands of different types, be aware of the implicit casts.
In particular :
which means some errors could happen, especially if one of the operand is converted from a numeric type to
- If any of the operands is of a reference type, unboxing conversion is performed. Then:
- If either operand is of type double, the other is converted to double.
- Otherwise, if either operand is of type float, the other is converted to float.
- Otherwise, if either operand is of type long, the other is converted to long.
- Otherwise, both operands are converted to type int.
double
or float
(see the INT33-J rule for more details regarding this issue), in which case some loss of precision errors could slip during the execution. You should therefore pay special attention to the bullets two and three in the previous list.
These conversions can happen with the following operators : multiplicative operators (%, *, /), additive opeators (+, -) comparisons (<, >, <=, >=) and equality (==, !=) operators and the integer bitwise operators (&, |, ^) and can be particularly harmful in the case of a conversion from an integral type to a floating point type (see INT33-J for more details), due to widening conversion.
In the following example,
int a = some_value; double b = some_other_value; double c = a + b;
a
is converted to double
before the + operator is applied.
A more complex example :
int a = some_value; char b = some_character; if( (a + b) == 0.0f){ //do something }
this time, b
is first converted to int
, then, the + operator is applied. The result of (a+b)
is then converted to float
, and the comparison operator is finally applied.
Here is an example of what could happen :
class Test{ public static void main(String[] args){ int big = 1999999999; double big_float = big; float one = 1.0f; System.out.println( (big * one) == big_float); } }
The output is false
, while ideally, it would be true
. big
is first converted to a float
, and loses some precision. The result of the multiplication is then converted to double
, and compared to big_float
, which hasn't lost precision, since it's a wider type than float
. The two operands are therefore different, and the comparison will return false
.
Risk assessment
If an operator is applied and some unexpected conversion occur, the result may be different from what the programmer and lead to some unexpected behavior and ultimately to a flaw or an abnormal termination.
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
EXP07-J |
low |
probable |
medium |
P4 |
L3 |
References
Java specification : "http://java.sun.com/docs/books/jls/third_edition/html/conversions.html".