Наследование обобщённых классов может выполняться следующими способами
- Потомок -- обобщённый класс:
class GenParent<T> {
T foo;
}
class GenChild<E> extends GenParent<E> {}
Класс-потомок предоставляет некий дополнительный обобщённый функционал, как и его предок. То есть у класса GenChild
указан (несвязанный unbounded) аргумент типа, и компилятор знает, что при использовании такого класса необходимо указать конкретный тип.
- Потомок -- конкретный класс
class IntChild extends GenParent<Integer> {}
Класс-потомок использует конкретный тип Integer
, наследуя обобщённый класс.
Здесь поле foo
(а также соответствующие геттеры/сеттеры/аргументы конструктора и т.д.) приобретает конкретный тип Integer
, известный компилятору.
- Потомок -- "сырой" (raw) класс
class RawChild extends GenParent {}
Не рекомендуемый способ, так как компилятор знает GenParent
-- обобщённый класс и не может найти требуемый конкретный тип, потому выдаёт предупреждение вида:
GenParent is a raw type. References to generic type GenParent should be parameterized
В данном случае такое объявление эквивалентно class RawChild extends GenParent<Object>
, о чем указано в комментарии Дмитрия, поле foo
становится типа Object
, и может принимать объекты любого типа, что характерно для типонебезопасного кодирования начала 2000-х годов до появления Java 1.5.