The final keyword does mean "no further change", so you're correct there. The issue here has to do with data "width".
An int can hold more data than a byte (i.e. it is "wider" than a byte). This means that when you do b = x, you're "narrowing" the width of the int to fit into the byte. This only works if the compiler can guarantee that the int is small enough to fit into the byte, which requires the int to be <= 127, and to also be final (so that it cannot later be changed to be > 127).
In your code, both x and y are narrow enough to fit into a byte, but only x is final, so it's the only one the compiler allows to be directly assigned to a byte variable.
final int x=127; final int y=100; // Made y final
byte b;
b=x; //Legal
b=y; //Also legal
final int x=200; final int y=100; // Made x too big
byte b;
b=x; //Illegal
b=y; //Legal