Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is causing this "possible loss of precision" error?

Tags:

java

final

I am having problem with my final variable. Any help will be greatly appreciated.

This is my first code which is working fine

final int i = 90; 
byte b = i ; 
System.out.println(i);

Here is my second code which says possible loss of precision. What is wrong here?

final int i; 
i = 90;
byte b = i ; 
System.out.println(i);
like image 295
Hello World Avatar asked Apr 17 '14 11:04

Hello World


2 Answers

I couldn't find the exact reason about this in JLS, so I went through the byte code and found that the reason is that the compiler couldn't inline the value of i in the second case, but is able to do it in the first case.

Here's the code:

final int x = 90; System.out.println(x);  final int i; i = 90; System.out.println(i); 

The compiled byte code looks like:

 0: getstatic     #2        // Field java/lang/System.out:Ljava/io/PrintStream;  3: bipush        90  5: invokevirtual #3        // Method java/io/PrintStream.println:(I)V  8: bipush        90 10: istore_2 11: getstatic     #2        // Field java/lang/System.out:Ljava/io/PrintStream; 14: iload_2 15: invokevirtual #3        // Method java/io/PrintStream.println:(I)V 18: return 

So in the first case (3 to 5), it directly uses the value 90 for printing, while in the second case (8 to 15), it has to store the value into the variable and then load it back onto the stack. Then the print method will pick the top value of the stack.

So, in case of the assignment:

byte x = i; 

The value of i will be picked up from the stack at runtime, and not inlined by the compiler. So the compiler doesn't know what value i might contain.

Of course, this is all my guess. The byte code might be different on different JVMs. But I've the strong intuition that this might be the reason.

Also, JLS §4.12.4 might be relevant here:

A variable of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28), is called a constant variable.

Since in the second case, the variable is not initialized by a constant expression, but is later assigned a value, it is no longer a constant variable.

like image 112
Rohit Jain Avatar answered Sep 20 '22 03:09

Rohit Jain


Simply, the first way the compiler "knows" that 90 can fit into a byte variable, but in the second, it can't detect the value of "i" and has no idea what value it might contain and therefore not sure it could fit into a byte variable or not.

like image 27
Tamim Al Manaseer Avatar answered Sep 20 '22 03:09

Tamim Al Manaseer