Shortcut Assignment Operators and Type Conversion

Shortcut Operators

We can use the following shortcut operators in the assignment of variables:

Operator Example Equivalent To
+= i += 8; i = i + 8;
-= i -= 2.0; i = i – 2.0;
*= i *= 13; i = i * 13;
/= i /= 5; i = i / 5;
%= i %= 2; i = i % 2;

Incrementing and decrementing a value by one is so common, there are special (even shorter) shortcut operators for these tasks:

Operator
(applied to myVar)
Name Description
++myVar Pre-Increment The expression (++myVar) adds 1 to myVar, and if used in or as an expression, it evaluates to this new (incremented) value of myVar.
myVar++ Post-Increment The expression (myVar++) also adds 1 to myVar, but if used in or as an expression, it evaluates to the original value of myVar (before the increment)
--myVar Pre-Decrement The expression (‐‐myVar) subtracts 1 from myVar, and if used in or as an expression, it evaluates to this new (decremented) value of myVar.
myVar-- Post-Decrement The expression (myVar‐‐) also subtracts 1 from myVar, but if used in or as an expression, it evaluates to the original value of myVar (before the decrement)

Be careful about using the increment and decrement operators within an expression. Consider
the following examples:

int i = 5;
int n = 3 * i++;
  has the same effect as  
int i = 5;
int n = 3 * i;
i = i + 1;

while

int i = 5;
int n = 3 * ++i;
  has the same effect as  
int i = 5;
i = i + 1;
int n = 3 * i;

Converting Values to Other Types

We often have to convert a data value of one type to another type, or mix data types within one expression.

If one converts a data value from one type to another that moves one from left to right in the list of types below, the conversion is called a widening conversion.

byte → short → int → long → float → double

  • Widening conversions do not lose information about the overall magnitude of a numeric value. Indeed, conversions widening from an integral type to another integral type and from float to double do not lose any information at all; the numeric value is preserved exactly.
  • Conversion of an int or a long value to float, or of a long value to double, may however, result in loss of precision, since floating-point types store their values in an inherently approximate way, while integral types store their values exactly.

If one converts a data value from one type to another in the reverse direction (right to left in the list above), the conversion is called a narrowing conversion.

  • Additionally, converting a long,float, or double type to a char type, and converting a char type to either a byte or short type, are also considered narrowing conversions.
  • Narrowing conversions may lose information about the overall magnitude of a numeric value and may also lose precision.

Types can be converted in three ways: implicitly by promotion, implicitly by assignment, and explicitly by casting.

Converting Types Implicitly by Promotion

Promotion occurs automatically in binary operations involving two operands of different types, and can happen in several ways:

The presence of one double promotes the other operand to a double

2D / 3      // 3 is treated as the double 3.0
1F + 6.72   // 1F is treated as the double 1.0

The presence of a float in the absence of a double promotes the other operand to a float

2.4F * 3    // 3 is treated as the float 3F
5L – 1.7F   // 5 is treated as the float 5F

The presence of a long in the absence of a double or float promotes the other operand to a long

3L + 2      // 2 is treated as the long 2L
16 % 2L     // 16 is treated as the long 16L

In the absence of doubles, floats, or longs, both operands are converted to the int type.

2 * 3       //both 2 and 3 are treated as type int.

Converting Types Implicitly by Assignment

Type conversion can also occur when a value of one type is assigned to a variable of another type.

Note, only widening conversions are allowed by assignment, as seen by the following examples:

double d = 100;   //this is a widening conversion, no problem
int n = 5.0;      //5.0 is a double, so this is a narrowing
                  //conversion. This creates a compiler error
int j = 2 + 6 / 3.0; //The presence of the "3.0" converts
                     //(by promotion) the 6 to a double.
                     //The quotient is then a double, which
                     //converts (by promotion) the 2 to a
                     //double. This gives a sum which is
                     //a double, which makes the assignment
                     //to j a narrowing conversion. Hence,
                     //this too creates a compiler error.

Converting Types Explicitly by Casting

To perform a narrowing conversion, we simply place the desired type in parentheses before the expression to be converted, in the following way:

(type) expression

Example:

(int) 5.0 //converts 5.0 to an int type

This "desired type in parentheses" is called a "cast operator". Be careful about the order of precedence for the cast operator. Casts happen after increments, decrements, and unary negatives, but before just about every other operator. This means the cast in the example below affects only the value of 5 and not the quotient :

double h = (double) 5 / 2;   //Note: h = 2.5

Casting without paying attention to the range of the data type can cause unexpected problems. Consider the following:

byte b = (byte) 500000;      //Here, b = 32 as
                             //500000 % 128 = 32
                             //Recall the size of a
                             //byte and the fact that
                             //128 = 2^7