Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declare Double as int compile vs not compile but appears same

Tags:

java

(note: Double is just an example)

When initializing a Double it needs a Double or double as value:

Double a = 0; //does not compile

unless you cast to double, or append 'd'

Double b = (double)0; //compiles
Double c = 0d; //compiles

When it becomes confusing is...
This compiles, although its value becomes 0 (int)

Double d = true ? 0 : 0d; //compiles, but always 0 (eclipse 'complains' on 0d calling it *Dead code*. So it knows it will return 0

As does this

Double e = false ? 0 : 0d; //compiles, always 0d

But these do not compile:

Double f = false ? 0 : 0; //cannot convert from int to Double
Double g = true ? 0 : 0; //cannot convert from int to Double

Why is it given an error for f and g but not for d

ps. Using Java8 (expect not a difference, but upgrades happen)

like image 470
Danielson Avatar asked Jan 09 '23 02:01

Danielson


2 Answers

It compiles because according to Java specs (at §15.25), if operands have different types and they're convertible to numeric types then binary numeric promotion applies (at §5.6.2):

Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

 If either operand is of type double, the other is converted to double.

It doesn't matter if double is first or second operand, result will be a double.

Going back to your examples:

Double e = false ? 0 : 0d; 
Double a = true ? 0 : 0d;

They're all converted to double because of numeric promotion however this:

Double f = false ? 0 : 0;

It will fail because result of condition ? 0 : 0 is always an integer, from §15.25 we know that:

If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression.

And assignment is invalid. Note that this exact case is used in specs to illustrate numeric promotion applied to ternary operators at §5.6.2-1:

class Test {
    public static void main(String[] args) {
        int i = 0;
        float f = 1.0f;

        // Omitted code...

        // Here int:float is promoted to float:float:
        f = (b==0) ? i : 4.0f;
        System.out.println(1.0/f);
    }
}

Finally note that your required final type (the one ternary operator expression will be used vs) doesn't play in this game and this code doesn't compile:

int n = true ? 0 : 0d; // Cannot assign a double to an int
like image 136
Adriano Repetti Avatar answered Jan 26 '23 11:01

Adriano Repetti


The ternary operator needs both values to be of a single type. Since you have an int and a double and there is a conversion possible from int to double without loss of precision*, they will both be converted.

Therefore if you do

Double d = true ? 1 : 2.0;

It is actually compiled as

Double d = true ? (double)1 : 2.0;

Therefore there will be no problems with the code. If both values are int, then the common type is int and no implicit conversion is made.

* with long and double or int and float there might not be possibility to convert without loss of precision since there aren't enough bits in the mantissa to represent all integer values exactly

like image 22
Sami Kuhmonen Avatar answered Jan 26 '23 11:01

Sami Kuhmonen