Have you heard of type erasure?
When you have a generic class like
List<String>, at runtime the generic type isn't used. The JVM treats it as a
List. The generic type information is used by the compiler to make sure all calls are safe, but it doesn't exist in the byte code*. This was done so that generic classes were backwards compatible with pre-generic classes - it's a bit of a pain at times, but that was the decision.
So when you write a class:
At runtime
T is just treated as
Object and it's more like:
In the
WordBox class, the difference is that
S is declared to extend
CharSequence. The
erasure of
S (meaning the class
S is considered to be at runtime) can therefore be more specific than
Object, and is
CharSequence. So the class gets translated as:
You can see the difference this makes if you delete the
extends CharSequence part. Then I get the following error (may depend on your compiler):
name clash: reset(S) in test.WordBox and reset(T) in test.Box have the same erasure, yet neither overrides the other
"Have the same erasure" is what I was talking about. The compiler knows they are different methods, so it doesn't consider this to be an override, but they'll both actually compile down to the same signature, which isn't allowed.
(* Technically I believe it does, but not in a way that makes a difference here)