Please take a look at below example i cant understand the relation between char and byte
byte b = 1;
char c = 2;
c = b; // line 1
Give me compilation Error because c is type of char
and b is type of byte
so casting is must in such condition
but now the tweest here is when i run below code
final byte b = 1;
char c = 2;
c = b; // line 2
line 2 compile successfully it doesn't need any casting at all
so my question is why char
c behave different when i use final access modifier with byte
Because qualifying it with final
makes the variable a constant variable, which is a constant expression. So
final byte b = 1;
char c = 2;
c = b; // line 2
actually becomes
final byte b = 1;
char c = 2;
c = 1;
And the compiler has a guarantee that the value 1
can fit in a char
variable.
With a non constant byte
variable, there is no such guarantee. byte
is signed, char
is unsigned.
You are running into JLS-5.1.4 Widening and Narrowing Primitive Conversion,
The following conversion combines both widening and narrowing primitive conversions:
First, the byte
is converted to an int
via widening primitive conversion (§5.1.2), and then the resulting int
is converted to a char
by narrowing primitive conversion (§5.1.3).
final byte b = 1;
char c = (char) ((int) 2); // <-- 2 is an int literal
c = (char) ((int) 1); // <-- b is 1 a byte literal
If you examine the bytescodes with javap -v
you'll see the the value 1 has already replaced the variable b
after compilation.
public static void main(java.lang.String[]) throws java.lang.Exception;
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Exceptions:
throws java.lang.Exception
Code:
stack=2, locals=3, args_size=1
0: iconst_1
1: istore_1 // b = 1
2: iconst_2
3: istore_2 // c = 2
4: iconst_1 // integer1.
5: istore_2 // c = 1.
I guess that it happens because java compiler replaces references to final
variables by their values (almost like pre-processor in C). Since value 1
is legal for type char
the last line is transformed to
c = 1;
that is compiled successfully.