The main point of this question is, what does the compiler know?
Consider this declaration.
1 is an int, but because 1 is a constant at compile-time, its value can be placed into a byte because it is known that 1 is small enough to be stored in a byte.
But then if you say
then the compiler will complain. Because all that it knows about b is that b is of type byte. A general byte cannot be stored directly in a char. The byte must first be converted to an int before it is stored in the char. This requires a cast.
However, if you have the declaration
then the compiler knows the value of b, not just that it is of type byte.
Since the value of b is a constant at compile-time, the compiler knows it can place the value of b into a char.
To answer your first question, you get loss of precision errors at both marks 1 and 4 in the following code.
The reason for this is the implicit casting that occurs when you use the assignment operator.
Mark 1 is a widening conversion, so you might expect it to be fine. The issue is that byte (and short) are signed in Java; char is unsigned, so it is possible to lose information during this conversion.
Mark 4 has a slightly different issue. The result of multiplying a char will be an int. Trying to assign the result to a short is a narrowing cast.
I love a woman who dresses in stainless steel ... and carries tiny ads: