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 statementWhen 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 statementAnd 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 statementAnd 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 compileAnd 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 snippetAlthough 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 snippetNow 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