Обобщения в Java: часть 1 - Обобщенная безопасность типов
ОГЛАВЛЕНИЕ
Обобщенная безопасность типов
Начнем с рассмотренного необобщенного примера, чтобы увидеть, как можно выиграть от обобщений. Переделаем вышеприведенный код, чтобы использовать обобщения. Измененный код показан ниже:
package com.agiledeveloper;
import java.util.ArrayList;
import java.util.Iterator;
public class Test
{
public static void main(String[] args)
{
ArrayList<Integer> list = new ArrayList<Integer>();
populateNumbers(list);
int total = 0;
for(Integer val : list)
{
total = total + val;
}
System.out.println(total);
}
private static void populateNumbers(ArrayList<Integer> list)
{
list.add(new Integer(1));
list.add(new Integer(2));
list.add("hello");
}
}
Используется ArrayList<Integer> вместо ArrayList. Сейчас при компиляции кода выдается ошибка компиляции:
Test.java:26: cannot find symbol
symbol : method add(java.lang.String)
location: class java.util.ArrayList<java.lang.Integer>
list.add("hello");
^
1 error
Параметризованный тип ArrayList обеспечивает безопасность типов.
Соглашения об именовании
Во избежание путаницы между обобщенными параметрами и настоящими типами в коде надо придерживаться продуманного соглашения об именовании. Если вы придерживаетесь продуманных соглашений Java и практик программирования, то наверняка не станете называть ваши классы одной буквой. Вы будете использовать смешанный регистр для имен классов, начиная с верхнего регистра. Ниже дано несколько соглашений, применяемых для обобщений:
• Использовать букву E для элементов коллекции, как в определении:
public class PriorityQueue<E> {…}
• Использовать буквы T, U, S и т.д. для универсальных типов.
Написание обобщенных классов
Синтаксис для написания обобщенного класса очень простой. Пример обобщенного класса:
package com.agiledeveloper;
public class Pair<E>
{
private E obj1;
private E obj2;
public Pair(E element1, E element2)
{
obj1 = element1;
obj2 = element2;
}
public E getFirstObject() { return obj1; }
public E getSecondObject() { return obj2; }
}
Этот класс представляет собой пару значений некоторого обобщенного типа E. Рассмотрим несколько примеров использования данного класса:
// Правильное использование
Pair<Double> aPair = new Pair<Double>(new Double(1), new Double(2.2));
Если попытаться создать объект с типами, которые не соответствуют, выдастся ошибка компиляции. Рассмотрим следующий пример:
// Неправильное использование
Pair<Double> anotherPair = new Pair<Double>(new Integer(1), new Double(2.2));
Здесь предпринимается попытка отправить экземпляр Integer и экземпляр Double экземпляру Pair. Однако это дает ошибку компиляции.