Search code examples
javashorttype-promotion

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


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?


Solution

  • 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