Pages

Java - Arithmetic compound assignment operators performing implicit type cast and automatic type conversion

The arithmetic compound assignment operators implicitly perform both automatic type conversion (widening conversion) and type casts the result of the arithmetic operation to the data type of destination variable.

The arithmetic compound assignment operators are given below

Operator
Explanation
+=
Addition assignment
-=
Subtraction assignment
*=
Multiplication assignment
/=
Division assignment
%=
Modulus assignment

The below example illustrates how automatic type conversion and implicit type cast is performed.


class Test {
       public static void main(String arg[]) {
              byte byteVar = 100;
              int intVar = 110;
              float floatVar = 1.2F;
              double doubleVar = 1.3D;

              byteVar *= doubleVar;          //Expression 1  
              byteVar = byteVar * doubleVar; // results in compilation error "Type mismatch: cannot convert from double to byte"
             
              intVar *= floatVar;            //Expression 2
              intVar = intVar * floatVar;    // results in compilation error "Type mismatch: cannot convert from float to int"
       }
}

 Explanation for Expression 1: (byteVar *= doubleVar)

Ø  Java compiler initially expands this expression into byteVar = byteVar * doubleVar

Ø  Then it type casts byteVar to double. So the expression becomes byteVar = (double)byteVar * doubleVar

Ø  Then it type casts whole right hand side expression to byte. So, the expression byteVar *= doubleVar finally internally converted into byteVar = (byte)((double)byteVar * doubleVar)

If we explicitly code “byteVar = byteVar * doubleVar” then compiler would throw "Type mismatch: cannot convert from double to byte" error. To avoid the compilation error we need to explicitly type cast the both byteVar and entire right hand side expression as shown above.

Explanation for Expression 2: (intVar *= floatVar)

Ø  Java compiler initially expands this expression into intVar = intVar * floatVar

Ø  Then it type casts intVar to float. So the expression becomes intVar = (float)intVar * floatVar

Ø  Then it type casts whole right hand side expression to int. So, the expression intVar *= floatVar finally internally converted into intVar = (int)((float)intVar * floatVar)

If we explicitly code “intVar = intVar * floatVar” then compiler would throw "Type mismatch: cannot convert from float to int". To avoid the compilation error we need to explicitly type cast the both intVar and entire right hand side expression as shown above.

Java - Widening conversion (Automat type promotion) in Expressions

This post explains how automatic type conversion works in expressions.

Rule 1:

In all the below assignment expressions, Java automatically promotes(widens) byte, char, short data types to ‘int’ data type and after that source variable(right hand side variable) is cast to the data type of destination variable (left hand side variable). So, all these expressions combine both widening and narrowing conversion at the same time.

byte = (byte) char
byte = (byte) short
char = (char) byte
char = (char) short
short = (short) char

Rule 2:

In an arithmetic expression, if the data type of one of operands is any one of byte, char, short and the other operand is integer literal constant, or both the operands are of byte, char, short type, then each operand is automatically promoted to int data type before performing arithmetic operation on them. Below table summarizes this concept.

Operand 1
Operator
Operand 2
Result
byte, char, short
Arithmatic operator

byte, char, short
Each operand is promoted to int before the arithmetic operation
(+, -, *, /, %)
byte, char, short
Arithmatic operator
integer literal constant
Operand 1 is promoted to int before the arithmetic operation
(+, -, *, /, %)

Rule 3:

If one of the operand is a long, the other operand in the expression is promoted to long. If one of the operand is a float, the other operand in the expression is promoted to float. If one of the operand is a double, the other operand in the expression is promoted to double. Below table summarizes this concept.

Operand 1
Operator
Operand 2
Result
byte, char, short, int
Arithmatic operator
float literal constant
Operand 1 is promoted to float before the arithmetic operation
(+, -, *, /, %)
byte, char, short, int
Arithmatic operator
double literal constant
Operand 1 is promoted to double before the arithmetic operation
(+, -, *, /, %)
byte, char, short, int
Arithmatic operator
float
Operand 1 is promoted to float before the arithmetic operation
(+, -, *, /, %)
byte, char, short, int, float
Arithmatic operator
double
Operand 1 is promoted to double before the arithmetic operation
(+, -, *, /, %)

Example:-

Let us examine how the ‘result’ expression is evaluated in the below example.

class Test {
       public static void main(String arg[]) {
              byte byteVar = 100;
              char charVar = 'x';
              short shortVar = 120;
              int intVar = 110;
              float floatVar = 1.2F;
              double doubleVar = 1.3D;
              double result = (((charVar + byteVar + shortVar) * intVar) + floatVar) + doubleVar;
              System.out.println("Result : " + result);             
       }
}

Step 1:  Operands in the expression (charVar + byteVar) is automatically promoted int and addition is performed and the result of this expression is int.

Step 2:  shortVar is promoted to int and it is added to the result of Step-1 and the result of this expression is also an int

Step 3:  Result of Step-2 which is an int, is multiplied by intVar and the result of this expression is also an int

Step 4: Result of step-3 is promoted to float and it is added to floatVar and the result of this expression is a float

Step 5: Result of step-4 is promoted to double and it is added to doubleVar and result is a double

Java Widening and narrowing conversions

When one type of variable (source) is assigned to another type of variable (destination), an automatic type conversion will occur if the type of the destination variable wide is enough and able to hold the entire range of the source variable. Automatic type conversion is also called as widening conversion.

Following table shows the width and ranges of primitive data types.

Type
Width in bits
How range is derived
Range
Char
16
2^16
0 to 65,536
Integer data types
Byte
8
(-2^7) to (2^7-1)
-128 to +127
Short
16
(-2^15) to (2^15-1)
-32,768 to +32,767
Int
32
(-2^31) to (2^31-1)
-2,147,483,648 to +2,147,483,647
Long
64
(-2^63) to (2^63-1)
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
Floating-point data types
Float
32
IEEE-754 standard
1.4e-045 to 3.4e+038
Double
64
IEEE-754 standard
4.9e-324 to 1.8e+308

In the below table, cells highlighted in Green results in the widening conversion and the cells highlighted in blue results in the “narrowing conversion”.

The cells highlighted in blue will result in compilation error unless we explicitly cast the source variable type to the destination variable type.

char = char
byte = byte
short = byte
int = char
long = char
float = char
double = char
char = byte
byte = char
short = short
int = byte
long = byte
float = byte
double = byte
char = short
byte  = short
short = char
int = short
long = short
float = short
double = short
char = int
byte  = int
short  = int
int = int
long = int
float = int
double = int
char = long
byte  = long
short  = long
int = long
long = long
float = long
double = long
char = float
byte  = float
short  = float
int = float
long = float
float = float
double = float
char = double
byte  = double
short  = double
int = double
long = double
float = double
double = double

Example for widening conversion
In the below example, char variable ‘charVar’ is assigned to an integer variable ‘intVar’. Since integer can hold entire range of char values, this assignment is allowed. Java internally converts the Unicode value of the ‘charVar’ to 32 bit integer value and assigns it to ‘intVar’.

class MyClass {
       public static void main(String arg[]) {
              int intVar;
              char charVar = 'x';
              intVar = charVar;
       }
}


Example for narrowing conversion
A ‘char’ variable cannot be assigned integer, floating-point variables because it won’t be able to hold entire range of those data types. So, to make the assignment to work, we need to explicitly cast the source variable type to char.

In the below example, integer variable ‘intVar’ is cast to ‘char’ to avoid the compilation error.

class MyClass {
       public static void main(String arg[]) {
              int intVar = 100;
              char charVar;
              charVar = (char)intVar;
       }
}


Note that narrowing conversion may result in the loss of precision.