Чтение онлайн

на главную - закладки

Жанры

Философия Java3

Эккель Брюс

Шрифт:

}

} /* Output: java.lang.String java.lang Integer java.lang.Double java.lang.Float java.lang.Character GenericMethods *///:-

Класс GenericMethods не параметризован, хотя и класс, и его методы могут быть параметризованными одновременно. Но в данном случае только метод f имеет параметр типа, обозначаемый списком параметров перед возвращаемым значением метода.

Учтите, что при использовании параметризованного класса параметры типов должны указываться при создании экземпляра. Но при использовании параметризованного метода указывать параметры

типа йе обязательно, потому что компилятор способен «вычислить» их за вас. Таким образом, вызов f выглядит как обычный вызов метода; создается впечатление, что метод f существует в бесконечном количестве перегруженных версий. При вызове ему даже может передаваться аргумент типа GenericMethods.

Для вызовов f, использующих примитивные типы, в действие вступает механизм автоматической упаковки — примитивные типы автоматически преобразуются в соответствующие объекты. Это позволяет исключить некоторые фрагменты кода, которые были необходимы прежде из-за явного выполнения преобразований.

Вычисление типа аргумента

Параметризацию иногда упрекают в том, что она увеличивает объем кода. Для наглядности возьмем пример holding/MapOfList.java из главы 11. Создание контейнера Map с List выглядит так:

Map<Person, List<? extends Pet» petPeople = new HashMap<Person, Li st<? extends Pet»:

(Ключевое слово extends и вопросительные знаки будут описаны позднее в этой главе.) Казалось бы, эта конструкция избыточна, а компилятор мог бы вычислить один из списков аргументов по-другому. В действительности сделать это он не может, но вычисление аргументов типов все же позволяет немного упростить код. Например, мы можем создать вспомогательную библиотеку с различными статическими методами, содержащими самые распространенные реализации различных контейнеров:

//: net/mindview/uti1/New.java

// Utilities to simplify generic container creation

// by using type argument inference.

package net mindview util; import java util *.

public class New {

public static <K.V> Map<K,V> map { return new HashMap<K.V>;

}

public static <T> List<T> list О { return new ArrayList<T>;

}

public static <T> LinkedList<T> 1 ListО { return new Li nkedLi st<T>.

}

public static <T> Set<T> setО { return new HashSet<T>;

}

public static <T> Queue<T> queueO { return new LinkedList<T>;

}

// Примеры:

public static void main(String[] args) {

Map<String, List<String>> sis = New.mapO; List<String> Is = New listO: Li nkedLi st<String> lis = New.lListO; Set<String> ss = New set; Queue<String> qs = New.queueO;

}

} ///-

Примеры использования представлены в main — вычисление аргументов типов устраняет необходимость в повторении списков параметров. Этот прием можно использовать в holding/MapOfList.java:

II- generics/SimplerPets.java import typeinfo.pets.*; import java util *; import net.mindview.util.*;

public class SimplerPets {

public static void main(String[] args) {

Map<Person, Li st<? extends Pet» petPeople = New map; //

Остальное без изменений...

}

} ///.-

Пример интересный, однако трудно сказать, насколько он эффективен в действительности. Человеку, читающему код, придется просмотреть дополнительную библиотеку и разобраться в ее коде. Возможно, вместо этого стоит оставить исходное (пусть и избыточное) определение — как ни парадоксально, этот вариант проще. Хотя, если в стандартную библиотеку Java будет добавлено некое подобие New.java, им можно будет пользоваться.

Вычисление типов не работает ни в каких других ситуациях, кроме присваивания. Если передать результат вызова метода (скажем, New.mapO) в аргументе другого метода, компилятор не пытается выполнить вычисление типа. Вместо этого вызов метода интерпретируется так, как если бы возвращаемое значение присваивалось переменной типа Object. Пример ошибки такого рода:

//: generics/LimitsOfInference.java import typeinfo.pets.*; import java.util.*;

public class LimitsOflnference { static void

f(Map<Person, List<? extends Pet» petPeople) {} public static void main(String[] args) {

// f(New.mapO); II He компилируется

}

} ///:-

Явное указание типа

При вызове параметризованного метода также можно явно задать тип, хотя на практике этот синтаксис используется редко. Тип указывается в угловых скобках за точкой, непосредственно перед именем метода. При вызове метода в пределах класса необходимо ставить this перед точкой, а при вызове статических методов перед точкой указывается имя класса. Проблема, продемонстрированная в LimitsOflnference.java, решается при помощи следующего синтаксиса:

//: generics/ExplicitTypeSpecification.java import typeinfo.pets.*: import java.util.*; i mport net.mi ndvi ew.uti1.*:

public class ExplicitTypeSpecification {

static void f(Map<Person, List<Pet>> petPeople) {} public static void main(String[] args) { f(New. <Person, Li st<Pet»map):

}

} ///:-

Конечно, при этом теряются преимущества от использования класса New для уменьшения объема кода, но дополнительный синтаксис необходим только за пределами команд присваивания.

Параметризованные методы и переменные списки аргументов

Параметризованные методы нормально сосуществуют с переменными списками аргументов:

II: generics/GenericVarargs.java import java.util.*;

public class GenericVarargs {

public static <T> List<T> makeList(T... args) { List<T> result = new ArrayList<T>; for(T item : args)

result.add(item);-return result;

public static void main(String[] args) { List<String> Is = makeListCA"); System out.println(ls); Is - makeListCA", "В". "С"); System.out.println(ls);

Поделиться:
Популярные книги

Тройняшки не по плану. Идеальный генофонд

Лесневская Вероника
Роковые подмены
Любовные романы:
современные любовные романы
6.80
рейтинг книги
Тройняшки не по плану. Идеальный генофонд

Барон играет по своим правилам

Ренгач Евгений
5. Закон сильного
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Барон играет по своим правилам

Завод-3: назад в СССР

Гуров Валерий Александрович
3. Завод
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Завод-3: назад в СССР

Секретарь лорда Демона

Лунёва Мария
Фантастика:
попаданцы
фэнтези
5.00
рейтинг книги
Секретарь лорда Демона

Отец моего жениха

Салах Алайна
Любовные романы:
современные любовные романы
7.79
рейтинг книги
Отец моего жениха

Идеальный мир для Лекаря 10

Сапфир Олег
10. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 10

Я тебя не отпущу

Коваленко Марья Сергеевна
4. Оголенные чувства
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Я тебя не отпущу

Бастард Императора. Том 7

Орлов Андрей Юрьевич
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 7

Девочка из прошлого

Тоцка Тала
3. Айдаровы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Девочка из прошлого

Вернуть невесту. Ловушка для попаданки 2

Ардова Алиса
2. Вернуть невесту
Любовные романы:
любовно-фантастические романы
7.88
рейтинг книги
Вернуть невесту. Ловушка для попаданки 2

Идеальный мир для Лекаря 7

Сапфир Олег
7. Лекарь
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 7

Хозяйка дома на холме

Скор Элен
1. Хозяйка своей судьбы
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Хозяйка дома на холме

Жена проклятого некроманта

Рахманова Диана
Фантастика:
фэнтези
6.60
рейтинг книги
Жена проклятого некроманта

Имя нам Легион. Том 9

Дорничев Дмитрий
9. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 9