Эккель Брюс
Шрифт:
//: 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);
Is = makeListC"ABCDEFFHIJKLMNOPQRSTUVWXYZ".split("")); System.out.printi n( Is);
}
} /* Output: [A]
[А, В. C]
[, А, В. C. D, E. F, F, H, I, J. K. L, M, N, 0. P. Q, R. S. T. U. V. W. X, Y, Z] *///•-
Метод makeList предоставляет ту же функциональность, что и метод java. util.Arrays.asList из стандартной библиотеки.
Использование параметризованных методов с Generator
Генераторы хорошо подходят для заполнения Collection, и для выполнения этой операции было бы удобно создать параметризованный метод:
//: generics/Genetcitors.java // Обобщенный метод заполнения коллекции import generics.coffee.*; import java.util.*; import net.mindview.util.*;
public class Generators {
public static <T> Collection<T>
fill(Collection<T> coll. Generator<T> gen, int n) { for(int i =0; i < n; i++)
coll .add(gen.nextO); return coll;
}
public static void main(String[] args) { Collection<Coffee> coffee = fill(
new ArrayList<Coffee>. new CoffeeGenerator. 4); for(Coffee с : coffee)
System.out.printin(c); Collection<Integer> fnumbers = fill(
new ArrayList<Integer>, new FibonacciO. 12); for(int i fnumbers)
System.out.printO + \ ");
}
} /* Output: Americano 0 Latte 1 Americano 2 Mocha 3
1. 1. 2. 3. 5. 8. 13. 21. 34. 55. 89. 144. *///:-
Обратите внимание на то, как параметризованный метод fill применяется к контейнерам и генераторам как для типа Coffee, так и для Integer.
Обобщенный генератор
Следующий класс создает генератор для любого класса, обладающего конструктором по умолчанию. Для уменьшения объема кода в него также включен параметризованный метод для получения BasicGenerator:
//: net/mindview/uti1/BasicGenerator java // Автоматическое создание Generator для класса // с конструктором по умолчанию (без аргументов) package net.mindview util;
public class BasicGenerator<T> implements Generator<T> { private Class<T> type;
public BasicGenerator(Class<T> type){ this.type = type; } public T nextО { try {
// Предполагается, что type является public-классом, return type.newlnstance; } catch(Exception e) {
throw new RuntimeException(e);
}
}
// Получение генератора по умолчанию для заданного type: public static <T> Generator<T> create(Class<T> type) { return new BasicGenerator<T>(type).
}
} ///:-
Класс предоставляет базовую реализацию, создающую объекты класса, который (1) является открытым (так как BasicGenerator определяется в отдельном пакете, соответствующий класс должен иметь уровень доступа public, не ограничиваясь пакетным доступом), и (2) обладает конструктором по умолчанию (то есть конструктором без аргументов). Чтобы создать один из таких объектов BasicGenerator, следует вызвать метод create и передать ему обозначение генерируемого типа, параметризованный метод create позволяет использовать запись BasicGenerator.create(MyType.class) вместо более громоздкой конструкции new BasicGenerator<MyType>(MyType.class).
Для примера рассмотрим простой класс с конструктором по умолчанию:
//: generics/CountedObject.java
public class CountedObject {
private static long counter = 0; private final long id = counter++; public long id { return id; }
public String toStringO { return "CountedObject " + id,} } ///:-
Класс CountedObject отслеживает количество созданных экземпляров и включает его в выходные данные toString.
При помощи BasicGenerator можно легко создать Generator для CountedObject: