Обобщения в Java: часть 1
ОГЛАВЛЕНИЕ
Аннотация
Java 5 (JDK 1.5) ввел принцип обобщений или параметризованных типов. Данная статья знакомит с принципами обобщений и показывает примеры их использования. В части II рассмотрено, как обобщения на самом деле реализованы в Java, и несколько проблем с применением обобщений.
Проблема безопасности типов
Java - строго типизированный язык. При программировании на Java во время компиляции надо знать, передается ли неверный тип параметра методу. Например, если определить:
Dog aDog = aBookReference; // ошибка
где aBookReference – ссылка типа Book, не связанная с Dog, вы получите ошибку компиляции.
Однако, к сожалению, при появлении Java, это не осуществлялось полностью в библиотеке Коллекции. Так, например, можно написать:
Vector vec = new Vector();
vec.add("hello");
vec.add(new Dog());
…
Не контролируется то, какой тип объекта помещается в Vector. Рассмотрим следующий пример:
package com.agiledeveloper;
import java.util.ArrayList;
import java.util.Iterator;
public class Test
{
public static void main(String[] args)
{
ArrayList list = new ArrayList();
populateNumbers(list);
int total = 0;
Iterator iter = list.iterator();
while(iter.hasNext())
{
total += ((Integer) (iter.next())).intValue();
}
System.out.println(total);
}
private static void populateNumbers(ArrayList list)
{
list.add(new Integer(1));
list.add(new Integer(2));
}
}
В программе выше создается ArrayList, заполняется некоторыми целыми значениями Integer, а затем значения суммируются путем извлечения Integer из ArrayList.
Вывод из вышеприведенной программы - значение 3, как ожидалось.
Что если изменить метод populateNumbers() следующим образом:
private static void populateNumbers(ArrayList list)
{
list.add(new Integer(1));
list.add(new Integer(2));
list.add("hello");
}
Ошибок компиляции не будет. Однако программа не выполнится правильно. Выдастся следующая ошибка при выполнении:
Exception in thread "main" java.lang.ClassCastException:
java.lang.String at com.agiledeveloper.Test.main(Test.java:17)…
До Java 5 в коллекциях не было безопасности типов.
Что такое обобщения?
В C++ есть такое прекрасное средство, как шаблоны. Шаблоны дают безопасность типов, в то же время, позволяя писать универсальный код, то есть не специфичный для какого-то конкретного типа. Хотя шаблоны C++ - очень мощный принцип, у него есть несколько недостатков. Во-первых, не все компиляторы хорошо поддерживают его. Во-вторых, он очень сложен в применении. Наконец, его применение имеет ряд неприятных особенностей (так можно сказать о C++ вообще, но это другая история). Когда появился Java, обошлись без большинства сложных средств C++, таких как шаблоны и перегрузка оператора.
Наконец, в Java 5 было решено ввести обобщения. Хотя обобщения – возможность писать универсальный или обобщенный код, независимый от конкретного типа – в принципе похожи на шаблоны в C++, есть ряд отличий. Например, в отличие от C++, где генерируются разные классы для каждого параметризованного типа, в Java есть только один класс для каждого обобщенного типа, независимо от того, экземпляры скольких разных типов создаются посредством него. Конечно, в обобщениях Java есть определенные проблемы, но они будут рассмотрены в части II. В части I рассматриваются преимущества.
Развитие обобщений в Java началось с проекта под названием GJ1 (обобщенный Java), начатого как расширение языка. Затем эту идею принял Процесс сообщества Java (JCP) в качестве Запроса спецификации Java (JSR) 142.