Murat Kutluer wrote:What about this one? Both int and long are larger primite than short, but int works, long doesn't.
That's very simple: because you can't assign a
long to a
short (or
int or
byte) without using an explicit cast.
Let's have a look at what happens behind the scenes. Remember that the compiler is often a very friendly guy, but sometimes can be very picky

Assume this statement
When the compiler sees that statement he has to decide if he must complain (compiler error) or not. So he probably thinks something like: "Hey dude, you know every integer literal is by default of type
int and you are trying to assign an
int to a
short without an explicit cast. That's not looking very good for you. But wait a minute, I don't offer any suffix (or other alternative) to create a
short literal (like with
L or
l for a
long) and
15 is within the range of
short, so I am not gonna complain about this statement. Otherwise you always have to write
short s1 = (short)15; and that's a lot of typing and clutters your code. I am such a friendly guy!

".
Now consider this statement
And again the compiler has to make up his mind about what to do with this statement: "I know you know that an integer literal is by default of type
int. And I know as well that you know I am happy to let it pass so you can save some key strokes, but
150_000 is not within range of
short! Do I need to assign 0, 15, 150, 1500, 15000, or ... to
s2? I really have no clue, so because I can't make this decision myself, I must create a compiler error for this statement. Sorry about that!"
Finally consider the following statement
And here is what the compiler thinks about this statement: "What are trying to pull off here, dude? You explicitly tell me to handle this literal as a
long literal by adding the
L suffix (or the
long cast as in your example. And then you want me to be ok about assigning a
long to a
short?

That definitely won't happen! You explicitly want me to treat that literal as a
long and a
long can't be assigned to a
short without explicit cast. Don't forget that allowing
short s1 = 15; was a friendly gesture of me to save you some typing (and also because you can't create a
short or
byte literal). But now you have explicitly turned the literal into a
long literal, so you have to face the consequences. Here is a big, fat, juicy compiler error!"
For the same reason, the following statement will also fail to compile
And just for the record, the
Java Language Specification is the only thing that matters for the compiler and this behavior is clearly mentioned in
§5.2. Assignment Contexts
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.
Finally I like to draw your attention to the following code snippet
Although both statement will have the same result (a primitive
long variable with a value of
15), there is a slight (but important) difference between both statements. On the first line the
int literal is implicitely widened to
long and that value is assigned to
lo1. On the second line a
long literal is simply assigned to
lo2. And that seems a minor difference, but is very important when you have a literal value which is outside the range of
int as you can see in this code snippet
Now
line1 and
line2 will fail to compile! Your very good friend, the compiler, considers
15_000_000_000 as an
int literal but
15_000_000_000 is outside the range of
int (resulting in a compiler error). On
line3 the compiler considers
15_000_000_000L as a
long literal and
15_000_000_000 is within the range of
long, so this statement compiles successfully. That's the short version of the explanation. If you want the more elaborate one, just read
this topic
Hope it helps!
Kind regards,
Roel