Узагальнений тип - це узагальнений клас або інтерфейс, параметризований типами. Це дає компілятору змогу забезпечити типобезпеку класу або інтерфейсу.
Розгляньмо цей неузагальнений інтерфейс Container:
class Container {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}
Оскільки він приймає та повертає типи Object, він працює з будь-яким непримітивним типом.
Однак за це доводиться платити: якийсь код може викликати get, розраховуючи на Integers, тоді як інший код викликає set, додаючи Strings, що призводить до винятку під час виконання.
Узагальнений клас і узагальнений інтерфейс мають такий вигляд:
class ClassName<T1, T2, ..., Tn> { ... }
interface InterfaceName<T1, T2, ..., Tn> { ... }
Розділ параметрів типу, обмежений кутовими дужками (<>), який іде після назви класу або інтерфейсу, задає параметри типу (їх ще називають змінними типу) T1, T2, ..., і Tn.
Їх можна використовувати всередині тіла класу або інтерфейсу, щоб забезпечити типобезпеку узагальнених типів.
Ось узагальнена версія Container:
class Container<E> {
private E object;
public void set(E object) { this.object = object; }
public E get() { return object; }
}
Тепер, коли ми його створюємо, нам треба оголосити, який тип він зберігає, і компілятор буде стежити за дотриманням цього обмеження:
// empty <> can infer from context
Container<String> stringContainer = new Container<>();
// compiler knows this is a String, so it is allowed
stringContainer.set("Some string");
// no cast needed, compiler knows it is a String
String result = stringContainer.get();
// this causes a compiler error:
stringContainer.set(42);