6

In the book of SCJP guide by Kathy Sierra, in the assignments chapter, we learn that we can declare something like this byte b = 7;. Behind the scene the code is byte b = (byte) 7;. This is so because in java, number 7 is considered a literal int value so has be to cast to int.

Now other situation. Double can include every byte contained within a float value as it is a bigger datatype. So can we say float f = 10.543; As 10.543 is quite a small value and should fit within a float. Also literal value for such number is considered a Double so compiler should implicitly cast it to float. But it's not so, compiler stops us. We have to append an F or f after that value.

Why are these two conflicting behaviour there for literal value assignment? In short if byte b = 7 is possible. Why is float f = 10.543 not possible?

Shades88
  • 7,934
  • 22
  • 88
  • 130
  • 1
    Because 10.543 is a *double* and the JLS *doesn't allow* for this implicit conversion (yes, this is *very precisely defined*). Try `float f = 10.543f`. There really needs to be no other reason than "the JLS says so". The reasoning behind such decisions can be argued for all day. –  Sep 14 '12 at 06:56

5 Answers5

6

You can read JLS 5.2 Assignment Conversion

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

If the type of the expression cannot be converted to the type of the variable by a conversion permitted in an assignment context, then a compile-time error occurs.

If the type of the variable is float or double, then value set conversion (§5.1.13) is applied to the value v

JLS #3.10.2.Floating-Point Literals

A floating-point literal is of type float if it is suffixed with an ASCII letter F or f; otherwise its type is double and it can optionally be suffixed with an ASCII letter D or d

5.1.2. Widening Primitive Conversion

A narrowing primitive conversion from double to float is governed by the IEEE 754 rounding rules (§4.2.4). This conversion can lose precision, but also lose range, resulting in a float zero from a nonzero double and a float infinity from a finite double. A double NaN is converted to a float NaN and a double infinity is converted to the same-signed float infinity.

I hope above clarifies your doubt.

Amit Deshpande
  • 19,001
  • 4
  • 46
  • 72
3

To add to the previous answers, the actual representation of 10.543 is:

Since you are actually specifying two different numbers, it makes sense to require an explicit declaration.

Flavio
  • 11,925
  • 3
  • 32
  • 36
  • The same could be said for the byte and int representation. – Denys Séguret Sep 14 '12 at 07:29
  • 2
    Not really: with `(byte) 42` and `(int) 42` you store *the same number* in two different binary representation. With `10.543f` and `10.543` you are actually specifying *two different numbers*. – Flavio Sep 14 '12 at 07:41
  • damn..that's cool. How can we find this actual representation? – Shades88 Sep 14 '12 at 09:13
  • The two rows in my answers are clickable, and you can find more info here: http://stackoverflow.com/questions/7644699/floating-point-representation – Flavio Sep 14 '12 at 10:14
1

A difference :

  • when you're "converting" from int to byte, you're just truncating the bytes
  • when you're converting from double to float, you're making a complex not trivial operation, which can't be implicit
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
1

Assigning a double to a float can cause precision loss, so java tells you you need to explicitly say how you want it to perform the assignment. Simple truncating may result in significant rounding errors.

Consider that a limited decimal in base 10 may actually be an unlimited fractional value in binary (e.g. floating point) base. Making conversion between floating point types explicit is therefore a good rule of thumb, useful in the vast majority of cases.

For integral types like byte the situation is slightly different: integral types can only differ on their size, but they all have the same decimal precision, which is zero. So there's no ambiguity in assigning a fitting value of a bigger integral type to a smaller integral variable.

user881430
  • 195
  • 1
  • 1
  • 11
1

"Behind the scene the code is byte b = (byte) 7".

That's not correct. See JLS #5.2 as referred to in several other answers. It says "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."

Nothing there about a typecast.

user207421
  • 305,947
  • 44
  • 307
  • 483