1. The add() method in class B does not override the add() method in class A, because the argument types are not the same. X and Y are subclasses of E and S, but they are not the same. Because of this, the method to call is determined at compile time, by looking at the type of the variable a, which is A (there is no dynamic dispatch, as you would have when there was overriding).
2. You can effectively make the ArrayList read-only by wrapping it like this:
When it says unmodifiableList, that means the List returned cannot be modified, but it remains a copy of the original List. Any changes to the original List are reflected in the unmodifiable copy, so I think it might have been better to call the method readOnlyList.