When executing calculations Java uses a "standard" datatype. When you are calculating with integers, the result of the calculation will be an int. That's why for example this code snippet won't compile (although you might think it would, it really doesn't ):

If you are doing some calculation with floating-points (decimals), the result will be a double. Again the reason why this won't compile too:

Also don't forget: when you use a floating-point literal value, it's automatically considered to be a double too. That's why you need to add an f (or F) when you need a float. So float f = 10.0; will not compile, but float f = 10.0F; does!

In your println-statement you are adding an int with a double, so the result will be a double (and thus 3.0 is printed)

Roel De Nijs wrote:When executing calculations Java uses a "standard" datatype. When you are calculating with integers, the result of the calculation will be an int. That's why for example this code snippet won't compile (although you might think it would, it really doesn't ):

If you are doing some calculation with floating-points (decimals), the result will be a double. Again the reason why this won't compile too:

Also don't forget: when you use a floating-point literal value, it's automatically considered to be a double too. That's why you need to add an f (or F) when you need a float. So float f = 10.0; will not compile, but float f = 10.0F; does!

In your println-statement you are adding an int with a double, so the result will be a double (and thus 3.0 is printed)

Ed Cardenas wrote:But after I tried to compile it, there was no error. How did that happen?

Yeah, it was a bit a trick question

The compiler is actually one smart cookie Because you used final for both variables, these are compile time constants. So the compiler knows the values of these variables and asks himself 1 question; does the value of the constant expression fit into the type of the variable? If it does, a narrowing primitive cast is used. If it doesn't, a compiler error is still given.

So for this example: the compiler knows there are 2 constants: 2 and 5, the value of the constant expression (2 + 5) is 7 and 7 fits the data type short, so compiler uses narrowing primitive cast (conversion) and no compiler error is given.

In addition, if the expression is a constant expression (§15.28) of type byte, short, char, or int: - A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.

So if you now know all this extra info, what would happen with this code snippets?

Roel De Nijs wrote: So if you now know all this extra info, what would happen with this code snippets?

My guess was right, this will compile because the value of the constant expression is 127 and fits in a byte (-128 to 127) through narrow primitive casting.

Again my guess was right that this code snippet won't compile.
Because of the value of the constant expression is 128, it can't fit into a byte (-128 to 127) so there is compiler error.
Thanks for the great explanation!

I have a question again Roel, when I tried to remove one of the final keyword on the code snippet below, why was there a compiler error?
Isn't the expression promoted to a compile time constant?

And just for completeness: you can only have a compile time constant if you are using a literal value (like 200 or 10). So invoking a method and putting the result in a variable marked as final will NOT result in a compile time constant.