I have read that char is treated separately when it comes to casting and it cannot be used with byte and short for narrowing or widening(but can be used with int,long,float ,double for widening)
You are correct, conversion between char and byte/short is norrowing conversion. If you see the code, s1 and c1 are declared final, compiler allows these conversions (char->byte/short) when the variables are delcared as final.
You remove the final keyword and you will see errors at line 3 and 4 also.
Once a final variable has been assigned, it always contains the same value. You are giving assurance to the compiler that the values (final short s1 =1; final char c1=1 will never change. That is the reason you are not getting error.
When ever you declare the variable is final the compiler not only knows the type also the value for that variable. Since in our case the variable is declared final and the short value is compatible with byte so no compilation error. Since the value is constant the compiler checks the value too...