Search code examples
javavariablesfinal

wht this type of final variable initialization not compile in java?


class Example{
  public static void main(String args[]){   
    final int x=127;

    final int y;
    y=100;

    byte b;

    b=x;
    b=y;
  }
}

Consider this program x and y variable declared as final variable. so I need to x and y value assigned to b. b=x; compiled and b=y; not compiled. why this code is not working correctly. please need explanation.


Solution

  • I don't have a real clue what are you trying to achieve by this code, but I might try explaining why it works for x and doesn't for y. I may misspell the strict nomenclature but it goes like this.

    One (and probably the main) reason behind this one working and another doesn't is because how compiler analizes the source code.
    Final keyword only means that the value cannot be changed once it's assigned/initialized (and the value must be initialized before accessing it).

    The b=x; assignment works, because the exact final value of x variable is known at compile time and the value of x is 127 which is in range of byte type. Therefore it can be assigned to the b - the x won't change because it's final and it's value is in range of byte and it's known at compile time.
    Going outside of byte range for x variable (e.g. 128) produces same error.

    The b=y; doesn't, because, as it might seem weird, the final value of y variable isn't known at compile time. The compiler doesn't go with all the instructions to evaluate the values of variables. Therefore the compiler doesn't know if between the initialization and declaration of y are other instructions that might be changing the value assigned to y. In other words, the value assigned to y is evaluated at runtime - because it's another instruction.

    The error seen with the b=y is:

    error: incompatible types: possible lossy conversion from int to byte
    

    The same error is produced when trying to do:

    int z = 126;
    final int zz=z;
    b=zz;
    

    or something like this:

    final int zz=new Scanner(System.in).nextInt();
    b=zz;
    

    In my zz and yours y cases the final value of that variables is evaluated at runtime and compiler doesn't know if their values won't overflow the range of b byte.

    Compiler isn't very smart thing or... is, but doesn't go with extensive optimizations and checking. Requiring from compiler to know that y=100 would make compilation time muuuch longer (because it would also need to go through evaluating the zz=new Scanner... expressions).

    It would also work with something like:

    final int x=127*2/2;
    b=x;
    

    Because the exact value of x can be evaluated at compile time.

    Let me know if you need some specification pages, I can look for them later.