Обобщения в 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. Однако это дает ошибку компиляции.