Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

According to the Java Language Specification (JLS) §4.2.2, "Integer Operations,"

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.

...

The JLS §5.6, "Numeric Promotions," describes numeric promotion as the following:

...

Widening conversions, resulting from integer promotions, preserves the overall magnitude of the number. However, promotions in which the operands are converted from an int to a float or from a long to a double can cause unexpected loss of precision. (See guideline "NUM17-J. Beware of precision loss when converting primitive integers to floating-point" for more details.)

These conversions can happen with the following operators: multiplicative operators (%, *, /), additive operators (+, -), comparison operators (<, >, <=, >=), equality operators (==, !=), and the integer bitwise operators (&, |, ^).

...

According to the JLS §15.26.2, "Compound Assignment Operators,"

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

...

In this noncompliant code example, a variable of type int (big) is multiplied by a value of type float one. In this case, numeric promotions require that big is promoted to the type float before the multiplication occurs, resulting in loss of precision. (See guideline "NUM17-J. Beware of precision loss when converting primitive integers to floating-point".)

Code Block
bgColor#ffcccc
class Test{
  public static void main(String[] args){
    int big = 1999999999;
    float one = 1.0f;
    // binary operation, loses precision because of implicit cast
    System.out.println(big * one); 
  }
}

...

Code Block
bgColor#ccccff
class Test{
  public static void main(String[] args){
    int big = 1999999999;
    double one = 1.0d; // double instead of float
    System.out.println(big*one);
  }
}

This solution produces the expected output of 1.999999999E9. This , which is the value that is obtained when an int is assigned (implicitly cast) to a double.

...

Code Block
bgColor#ccccff
int result = 0;
for (int i = 0; i < 4; i++) 
  result = ((result << 8) | (b[i] & 0xff));

Noncompliant Code Example (Compound Addition

...

and Assignment)

This noncompliant code example performs a compound assignment operation. This operation involves an int value that contains too many significant bits to fit in the twenty23-three bit mantissa of a Java float, causing the widening conversion from int to float to lose precision. The resulting value could surprise many programmers.

Code Block
bgColor#FFCCCC
public class Expr {
  public static void main(String[] args) {
    int x = 2147483642; // 0x7ffffffa
    x += 1.0f; // x contains 2147483647 (0x7fffffff) after the computation
  }
}

Compliant Solution (Compound Addition

...

and Assignment)

To be safe, avoid using any of the compound assignment operators on variables of types byte, short, or char. Also, refrain from using a wider operand on the right-hand side. In this compliant solution, all operands are of the Java type double.

Code Block
bgColor#ccccff
public class Expr {
  public static void main(String[] args) {
    double x = 2147483642; // 0x7ffffffa
    x += 1.0; // x contains 2147483643.0 (0x7ffffffb.0) as expected
  }
}

Noncompliant Code Example (Compound Bit Shift

...

and Assignment)

This noncompliant code example uses a compound right-shift operator for shifting the value of i, bit by bit. Unfortunately, the value of i remains the same. The value of i is first promoted to an int. This is a widening primitive conversion, so no data is lost. With short, -1 is represented as 0xffff. The conversion to int results in the value 0xffffffff, which is right shifted by 1 bit to yield 0x7fffffff. To store the value back into the short variable i, Java then performs an implicit narrowing conversion, discarding the 16 higher order bits. The final result is again 0xffff, or -1.

Code Block
bgColor#FFCCCC
short i = -1;
i >>>= 1;

Compliant Solution (Compound Bit Shift

...

and Assignment)

This compliant solution applies the compound assignment operator to an int, which does not require widening and subsequent narrowing.

...

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="1b5f3a887bf85836-3adbd6d3-47e34082-8a82adcc-5454b9a35cae387cd359a70f"><ac:plain-text-body><![CDATA[

[[Bloch 2005

AA. References#Bloch 05]]

Puzzle 9: "Tweedledum"

]]></ac:plain-text-body></ac:structured-macro>

 

Puzzle 31: "Ghost of Looper"

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="05926b09fc74a50c-60094f1a-4e064282-85c88bb1-ccc69af418b448adf3c90a13"><ac:plain-text-body><![CDATA[

[[Findbugs 2008

AA. References#Findbugs 08]]

"BIT: Bitwise OR of signed byte value"

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="37c2b5179114b54a-9d640c1a-4dc144c7-b93a915a-360071839809559d567538f9"><ac:plain-text-body><![CDATA[

[[JLS 2005

AA. References#JLS 05]]

[§4.2.2, "Integer Operations"

http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.2]

]]></ac:plain-text-body></ac:structured-macro>

 

§5.6, "Numeric Promotions"

 

§15.26.2, "Compound Assignment Operators"

...