Why is "short thirty = 3 * 10" a legal assignment?

JavaShortType Promotion

Java Problem Overview


If short is automatically promoted to int in arithmetic operations, then why is:

short thirty = 10 * 3;

A legal assignment to the short variable thirty?

In turn, this:

short ten = 10;
short three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED

as well as this:

int ten = 10;
int three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED

does not compile because assigning an int value to a short is not allowed without casting as expected.

Is there something special going on about numerical literals?

Java Solutions


Solution 1 - Java

Because the compiler replaces 10*3 with 30 at compile time itself. So,effectively : short thirty = 10 * 3 is calculated at compile time.

Try changing ten and three to final short (making them compile time constants) and see what happens :P

Examine byte-code using javap -v for both verisions (10*3 and final short). You will be able to see that there is little difference.

Ok, So, here is the byte code difference for different cases.

Case -1 :

> Java Code : main() { short s = 10*3; }

Byte code :

stack=1, locals=2, args_size=1
         0: bipush        30  // directly push 30 into "s"
         2: istore_1      
         3: return   

Case -2 :

public static void main(String arf[])  {
   final short s1= 10;
   final short s2 = 3;
   short s = s1*s2;
}

Byte code :

  stack=1, locals=4, args_size=1
         0: bipush        10
         2: istore_1      
         3: iconst_3      
         4: istore_2      
         5: bipush        30 // AGAIN, push 30 directly into "s"
         7: istore_3      
         8: return   

Case -3 :

public static void main(String arf[]) throws Exception {
	 short s1= 10;
	 short s2 = 3;
	 int s = s1*s2;
}

Byte-code :

stack=2, locals=4, args_size=1
         0: bipush        10  // push constant 10
         2: istore_1      
         3: iconst_3        // use constant 3 
         4: istore_2      
         5: iload_1       
         6: iload_2       
         7: imul          
         8: istore_3      
         9: return 

   

In the above case, 10 and 3 are taken from the local variables s1 and s2

Solution 2 - Java

Yes there is something special going on with the literal case: 10 * 3 will be evaluated at compile time. So you don't need an explicit (short) conversion for multiplied literals.

ten * three is not compile-time evaluable so therefore needs an explicit conversion.

It would be a different matter if ten and three were marked final.

Solution 3 - Java

The following answer adds the JLS section and some details about this behavior.

As per JLS §15.2 - Forms of Expressions

> Some expressions have a value that can be determined at compile time. > These are constant expressions (§15.28).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCeiling GeckoView Question on Stackoverflow
Solution 1 - JavaTheLostMindView Answer on Stackoverflow
Solution 2 - JavaBathshebaView Answer on Stackoverflow
Solution 3 - JavaNicolas HenneauxView Answer on Stackoverflow