Если коротко, то Generics — это способ сказать, что класс, интерфейс или метод будут работать не с каким-то конкретным типом, а просто с каким-то. С каким именно будет определено из контекста. Например:
public interface List<E> extends Collection<E> {
//...
}
Заранее неизвестно, объекты какого класса будут содержаться в списке, но это определится при его использовании:
List<String> list = new ArrayList<>();
Теперь это не просто список, а список строк. Generics помогают обеспечить типобезопасность: в List можно попытаться положить любой объект, но в List<String> — только String или один из его потомков.