2
byte b1=1,b2=2,b3,b6; 
final byte b4=4,b5=6; 
b6=b4+b5;    // line3
b3=b1+b2;    // line4: error: incompatible types: possible lossy conversion from int to byte
System.out.println(b3+b6);

Why line 3 is right? It seems the type is not correct and I should be getting the error I get on line 4.

Live example on ideone

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
GsM
  • 161
  • 1
  • 1
  • 13
  • possible duplicate of [How final keyword works](http://stackoverflow.com/questions/15655012/how-final-keyword-works) – Patrick Collins Aug 14 '15 at 08:20
  • 1
    What compiler error message are you getting? Usually those contain helpful information. – Thilo Aug 14 '15 at 08:22
  • 1
    Presumably since `b4` and `b5` are `final`, the compiler knows that they are in a suitable range to add into a `byte` variable...? – khelwood Aug 14 '15 at 08:23
  • 2
    Please review the edits I've made to your question. Always include the actual error message and avoid irrelevant differences when comparing two lines (the `()`). Half-decent variable names would have helped a lot, too. It's a really interesting question, but the way it was asked lead to it being downvoted. – T.J. Crowder Aug 14 '15 at 08:27
  • 1
    @PatrickCollins - definitely not a duplicate of [that question](http://stackoverflow.com/q/15655012/1945631). – Andy Brown Aug 14 '15 at 08:42
  • @AndyBrown You're right, I assumed he was getting a generic "can't reassign a final variable", with the error message in I see that it was something surprising. Retracted. – Patrick Collins Aug 14 '15 at 08:44

2 Answers2

8

The error occurs on line 4 and not line 3 because the compiler knows the values of the final variables, but doesn't know the values of the non-final variables. The compiler sees final and that the variable is definitely assigned prior to use with a constant value, and as the variable is final, that value cannot be changed. Since the compiler knows the values, it knows that there is no loss in the conversion of the value 10 (b4+b5). In fact, they're effectively constants and you're doing b6=10 — and if you look at the bytecode generated if we remove line 4 and adjust line 6, we see that that's exactly what the compiler does: Optimizes b4 and b5 away entirely.

If you chose different values for b4 and b5 (100, for instance), you'd get an error on line 3 as well:

byte b1=1,b2=2,b3,b6; 
final byte b4=100,b5=100; 
b6=b4+b5;  // line3 error: incompatible types: possible lossy conversion from int to byte
b3=b1+b2;  // line4 error: incompatible types: possible lossy conversion from int to byte
System.out.println(b3+b6);

Live on ideone

Here's something demonstrating this, that will compile

byte b1=1,b2=2,b3,b6; 
final byte b4=4,b5=6; 
b6=b4+b5;  // line3
//b3=b1+b2;  // line4
//System.out.println(b3+b6);
System.out.println(b6);

And here's the disassembly:

public static void main(java.lang.String[]) throws java.lang.Exception;
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_2
       3: istore_2
       4: bipush        10
       6: istore        4
       8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      11: iload         4
      13: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      16: return

Note the

4: bipush        10
6: istore        4

...which is storing the literal value 10 in b6.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
-1

How does JVM process keyword “final” ? JVM in runtime doesn't know about this modifier. Compilator does.

Your issue isn't about final, to eliminate error do this:

b3=(byte)(b1+b2);   // line isn't invalid now

One time assignment to a final variable defined earlier is a valid statement itself.

Line 3 - compiler just inline your values as integer constant.

   L4
    LINENUMBER 30 L4
    BIPUSH 10
    ISTORE 4

Line 4 - compiler can't do this.

   L5
    LINENUMBER 31 L5
    ILOAD 1
    ILOAD 2
    IADD
    I2B
    ISTORE 3

Read next: http://www.javatpoint.com/final-keyword

Les
  • 242
  • 1
  • 4
  • 13
  • 4
    This doesn't answer the question. Why does he need that for line 4 and not for line 3? – T.J. Crowder Aug 14 '15 at 08:27
  • This depends. Actually, need for line 3 too, but compiler do your work inlining the final values and conclude that there isn't overflow. – Les Aug 14 '15 at 08:49