Promotion in Java

Promotion in Java?

There's no + operator for byte. Instead, both operands are promoted to int, so you've got

byte = byte + byte
... becomes (widening to find + operator) ...
byte = int + int
... becomes (result of + operator) ...
byte = int

... which then fails because there's no implicit conversion from int to byte. You need to cast:

byte a = 1;
byte b = 2;

byte c = (byte) (a + b);

Here are the actual rules for numeric promotion, from section 5.6.2 of the JLS:


When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order, using widening conversion (§5.1.2) to convert operands as necessary:

  • If any of the operands is of a reference type, unboxing conversion (§5.1.8) 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.

Promotion in java

It's important to remember the order of operations!

3.0 + 5/2
3.0 + (5/2)
3.0 + 2
3.0 + 2.0
5

5/2 executes first, giving back 2.

Hope this helps!

What is numeric promotion?

Numeric promotion is the conversion of a smaller numeric type to a larger numeric type, so that integer and floating-point operations may take place. In numerical promotion, byte, char, and short values are converted to int values. The int values are also converted to long values, if necessary. The long and float values are converted to double values, as required.

Java type promotion in parameters

I think this has something to do with JLS's specific rule about 15.12.2.5. Choosing the Most Specific Method. It states that:

If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.

How Java chooses the most specific method is further explained by the text:

The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time error. In cases such as an explicitly typed lambda expression argument (§15.27.1) or a variable arity invocation (§15.12.2.4), some flexibility is allowed to adapt one signature to the other.

In the case of your example, all methods are accessible and applicable to method invocation, therefore, Java needs to determine which of them is most specific.

For these methods, none can be determined to be more specific:

public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
} // int, double cannot be passed to long, long or double, long without error

public static void printSum(long a, long b) {
System.out.println("In long " + (a + b));
} // long , long cannot be passed to int, double or double, long without error

public static void printSum(double a, long b) {
System.out.println("In doubleLONG " + (a + b));
} // double, long cannot be passed to int, double or long, long without error

The fourth method clears ambiguity precisely because it fulfills the necessary condition to be most specific.

public static void printSum(int a, long b) {
System.out.println(String.format("%s, %s ", a, b));
}

That is, (int, long) can be passed to (int, double), (long, long), or (double, long) without compilation errors.

How numeric promotion and demotion works for literals and variables in Java?

You could check the following two links out:

  • Why explicit type casting required from double to float but not from int to byte?
    (the one I have already shared in a comment)
  • Implicit type cast not working for method parameters?

By the way, both of those questions were answered by the #1 StackOverflow contributor Jon Skeet :)

Promotion and conversion in java

This is okay because you are giving constant value. See compile-time narrowing of constants.

The compile-time narrowing of constants means that code such as:

byte theAnswer = 42;

is allowed. Without the narrowing, the fact that the integer literal 42 has type int would mean that a cast to byte would be required:

byte theAnswer = (byte) 42; // cast is permitted but not required

primitive promotion for [Java]

The JLS won't "promote to the larger datatype" here, because it does not perform binary numeric promotion for shifting operators. This is covered by the JLS, Section 15.19.

Unary numeric promotion (§5.6.1) is performed on each operand separately. (Binary numeric promotion (§5.6.2) is not performed on the operands.)

Unary numeric promotion promotes the byte a to an int. The literal 4L is not changed, but it only needs to be a integral type anyway.

It is a compile-time error if the type of each of the operands of a shift operator, after unary numeric promotion, is not a primitive integral type.

Then for the shifting, only the least 5 significant bits are used to shift an int.

If the promoted type of the left-hand operand is int, then only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.

The result of the operator is an int, not a long, so it can be assigned to an int without a compiler error.

The type of the shift expression is the promoted type of the left-hand operand.



Related Topics



Leave a reply



Submit