Spec-Zone .ru
спецификации, руководства, описания, API
След: Изучение Языка Java
Урок: (Обновленные) Обобщения
Универсальные Типы
Домашняя страница > Изучение Языка Java > (Обновленные) обобщения

Универсальные Типы

Универсальным типом является универсальный class, или взаимодействуйте через интерфейс, который параметризован по типам. Следующий Box class будет изменен, чтобы демонстрировать понятие.

Простой Класс Поля

Начните, исследуя неуниверсальный Box class, который работает на объектах любого типа. Это должно только обеспечить два метода: set, который добавляет объект к полю, и get, который получает это:

public class Box {
    private Object object;

    public void set(Object object) { this.object = object; }
    public Object get() { return object; }
}

Так как его методы принимают или возвращают Object, Вы свободны передать, в чем Вы хотите, при условии, что это не одни из типов примитивов. Нет никакого способа проверить, во время компиляции, как class используется. Одна часть кода может поместить Integer в поле и ожидать получать Integer s из этого, в то время как другая часть кода может по ошибке передать в String, приводящем к ошибке периода выполнения.

Универсальная Версия Класса Поля

Универсальный class определяется с помощью следующего формата:

class name<T1, T2, ..., Tn> { /* ... */ }

Раздел параметра типа, разграниченный угловыми скобками (<>), следует за именем class. Это определяет параметры типа (также названный переменными типа) T1, T2..., и Tn.

Чтобы обновить Box class, чтобы использовать обобщения, Вы создаете универсальное описание типа, изменяя код "public class Box" на "public class Box<T>". Это представляет переменную типа, T, который может использоваться где угодно в class.

С этим изменением Box class становится:

/**
 * Generic version of the Box class.
 * @param <T> the type of the value being boxed
 */
public class Box<T> {
    // T stands for "Type"
    private T t;

    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

Как можно видеть, все возникновения Object заменяются T. Переменная типа может быть любым нетипом примитива, который Вы определяете: любой тип class, любой тип интерфейса, любой тип массива, или даже другая переменная типа.

Этот тот же самый метод может быть применен, чтобы создать универсальные интерфейсы.

Введите Соглашения о присвоении имен Параметра

Условно, введите названия параметра, единственные, прописные буквы. Это стоит в резком контрасте переменным соглашениям о присвоении имен, которые Вы уже знаете о, и с серьезным основанием: Без этого соглашения было бы трудно сказать различие между переменной типа и обычным class или именем интерфейса.

Обычно используемые названия параметра типа:

Вы будете видеть эти имена, используемые всюду по Java API SE и остальная часть этого урока.

Вызов и Инстанцирование Универсального Типа

Чтобы сослаться на универсальный Box class изнутри Вашего кода, следует выполнить универсальный вызов типа, который заменяет T некоторым конкретным значением, таким как Integer:

Box<Integer> integerBox;

Можно думать об универсальном вызове типа, как являющемся подобным обычному вызову метода, но вместо того, чтобы передать параметр методу, Вы передаете параметр типаInteger в этом случае — к Box class непосредственно.


Введите Терминологию Параметра Параметра и Типа: Много разработчиков используют термины "параметр типа", и "вводят параметр" взаимозаменяемо, но эти сроки не являются тем же самым. Кодируя, каждый обеспечивает параметры типа, чтобы создать параметризованный тип. Поэтому, T в Foo<T> является параметром типа, и String в Foo<String> f является параметром типа. Этот урок наблюдает это определение при использовании этих сроков.

Как любое другое объявление переменной, этот код фактически не создает новый объект Box. Это просто объявляет, что integerBox будет содержать ссылку на "Box Integer", который является, как Box<Integer> читается.

Вызов универсального типа является общеизвестным как параметризованный тип.

Чтобы инстанцировать этого class, используйте ключевое слово new, как обычно, но поместите <Integer> между именем class и круглой скобкой:

Box<Integer> integerBox = new Box<Integer>();

Ромб

В Java SE 7 и позже, можно заменить параметры типа, требуемые вызвать конструктора универсального class с пустым множеством параметров типа (<>), пока компилятор может определить, или вывести, параметры типа от контекста. Эту пару угловых скобок, <>, неофициально вызывают ромбом. Например, можно создать экземпляр Box<Integer> со следующим оператором:

Box<Integer> integerBox = new Box<>();

Для получения дополнительной информации по ромбовидной нотации и выводу типа, см. Вывод типа.

Многократные Параметры Типа

Как упомянуто ранее, у универсального class могут быть многократные параметры типа. Например, универсальный OrderedPair class, который реализует универсальный интерфейс Pair:

public interface Pair<K, V> {
    public K getKey();
    public V getValue();
}

public class OrderedPair<K, V> implements Pair<K, V> {

    private K key;
    private V value;

    public OrderedPair(K key, V value) {
	this.key = key;
	this.value = value;
    }

    public K getKey()	{ return key; }
    public V getValue() { return value; }
}

Следующие операторы создают два инстанцирования OrderedPair class:

Pair<String, Integer> p1 = new OrderedPair<String, Integer>("Even", 8);
Pair<String, String>  p2 = new OrderedPair<String, String>("hello", "world");

Код, new OrderedPair<String, Integer>, инстанцирует K как String и V как Integer. Поэтому, типами параметра конструктора OrderedPair является String и Integer, соответственно. Из-за автоупаковки, это допустимый, чтобы передать String и int к class.

Как упомянуто в Ромбе, потому что компилятор Java может вывести K и типы V от объявления OrderedPair<String, Integer>, эти операторы могут быть сокращены, используя ромбовидную нотацию:

OrderedPair<String, Integer> p1 = new OrderedPair<>("Even", 8);
OrderedPair<String, String>  p2 = new OrderedPair<>("hello", "world");

Чтобы создать универсальный интерфейс, следуйте за теми же самыми соглашениями что касается создания универсального class.

Параметризованные Типы

Можно также заменить параметром типа (то есть, K или V) с параметризованным типом (то есть, List<String>). Например, используя пример OrderedPair<V, K>:

OrderedPair<String, Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));

Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Почему Обобщения Использования?
Следующая страница: Необработанные Типы