Рассмотрим пример, в котором вы должны составить список живых существ в местности. Неважно, человек это, животное или растение. Все, что имеет значение, является живым существом. В этом случае вы бы сгруппировали их как «живые существа», а не классифицировали их.
Точно так же, когда вам нужно хранить некоторые данные, для вас важен контент, а не тип данных, и именно здесь вы используете дженерики. Обобщения в Java — это языковая функция, которая позволяет использовать универсальные типы и методы.
Что такое Generics в Java?
Дженерики в Java — это термин, обозначающий набор языковых возможностей, связанных с определением и использованием общих типов и методов. Общие методы Java отличаются от обычных типов данных и методов. До Generics мы использовали коллекцию для хранения любых типов объектов, т.е. неуниверсальных. Теперь Generics заставляет программиста Java хранить объекты определенного типа.
Если вы посмотрите на классы платформы Java-коллекции, то увидите, что большинство классов принимают параметр / аргумент типа Object. По сути, в этой форме они могут принимать любой тип Java в качестве аргумента и возвращать один и тот же объект или аргумент. Они в основном неоднородны, т.е. не похожего типа.

Иногда в приложении Java тип данных ввода не является фиксированным. Входными данными могут быть целое число, число с плавающей запятой или строка. Чтобы назначить ввод переменной правильного типа данных, необходимо было провести предварительные проверки.
В традиционном подходе после получения ввода проверяется тип данных ввода, а затем назначается переменная правого типа данных. При использовании этой логики длина кода и время выполнения были увеличены. Чтобы избежать этого, были введены дженерики.
Когда вы используете Generics, параметры в коде автоматически проверяются во время компиляции, и он устанавливает тип данных по умолчанию. Так что это то место, где вам нужна концепция обобщений в Java.
Существует 4 различных способа применения:
- Типовой класс
- Интерфейс
- Метод
- Конструктор
1. Типовой класс
Класс называется дженериком, если он объявляет одну или несколько переменных типа. Эти типы переменных известны как параметры типа класса Java. Давайте разберемся с этим на примере. В приведенном ниже примере я создам класс с одним свойством x, а типом свойства является объект.
class Genericclass{
private Object x;
public void set(Object x) { this.x = x; }
public Object get() { return x; }
}
Здесь, как только вы инициализируете класс с определенным типом, класс должен использоваться только с этим конкретным типом. Например, если вы хотите, чтобы один экземпляр класса содержал значение x типа ‘String’, программист должен установить и получить единственный тип String.
Поскольку я объявил тип свойства для объекта, нет никакого способа применить это ограничение. Программист может установить любой объект и может ожидать любой тип возвращаемого значения от метода get, поскольку все типы Java являются подтипами класса Object.
Чтобы применить этот тип ограничения, мы можем использовать обобщенные значения, как показано ниже:
class Genericclass<X> {
//T stands for "Type"
private T x;
public void set(T x) { this.x = x; }
public T get() { return x; }
}
Теперь вы можете быть уверены, что класс не будет неправильно использоваться с неправильными типами. Простой пример «Genericclass» выглядит так, как показано ниже:
Genericclass<String> instance = new Genericclass<String>();
instance.set("Edureka");
instance.set(10); //This will raise compile time error
Эта аналогия верна и для интерфейса.
2. Интерфейс
Интерфейс в Java относится к абстрактным типам данных. Они позволяют манипулировать коллекциями Java независимо от деталей их представления.
Кроме того, они образуют иерархию в объектно-ориентированных языках программирования.
//Generic interface definition
interface GenericInterface<T1, T2>
{
T2 PerformExecution(T1 x);
T1 ReverseExecution(T2 x);
}
//A class implementing generic interface
class Genericclass implements GenericInterface<String, Integer>
{
public Integer PerformExecution(String x)
{
//execution code
}
public String ReverseExecution(Integer x)
{
//execution code
}
}
3. Методы
Универсальные методы очень похожи на универсальные классы. Они отличаются друг от друга только одним аспектом, заключающимся в том, что информация о области действия или типе находится только внутри метода. Универсальные методы вводят свои параметры типа.
public static <T> int countAllOccurrences(T[] list, T element) {
int count = 0;
if (element == null) {
for ( T listElement : list )
if (listElement == null)
count++;
}
else {
for ( T listElement : list )
if (element.equals(listElement))
count++;
}
return count;
}
Если вы передадите список String для поиска в этом методе, он будет работать нормально. Но если вы попытаетесь найти число в списке строк, это даст ошибку времени компиляции.
4. Конструктор
Конструктор Java — это блок кода, который инициализирует вновь созданный объект. Конструктор напоминает метод экземпляра в Java, но это не метод, поскольку он не имеет возвращаемого типа. Конструктор имеет то же имя, что и класс, и выглядит так в коде Java.
class Dimension<T>
{
private T length;
private T width;
private T height;
//Generic constructor
public Dimension(T length, T width, T height)
{
super();
this.length = length;
this.width = width;
this.height = height;
}
}
В приведенном выше примере конструктор класса Dimension содержит информацию о типе. Таким образом, вы можете иметь экземпляр измерения со всеми атрибутами только одного типа.
Преимущества дженериков в Java
1. Повторное использование кода.
Вы можете составить стратегию, класс или интерфейс один раз и использовать их для любого типа или любым другим способом.
2. Кастинг отдельных типов не требуется.
По сути, вы восстанавливаете информацию из ArrayList каждый раз, когда вам нужно ее типизировать.
Типирование при каждой задаче восстановления является серьезной задачей. Чтобы искоренить этот подход, были введены дженерики.
3. Реализация неуниверсального алгоритма.
Он может рассчитывать алгоритмы, которые работают с различными типами элементов, которые также являются безопасными типами.
