'throw new RuntimeException(e);
}
}
class Coffeelterator implements Iterator
public boolean hasNextO { return count > 0. } public Coffee next О { count--;
return CoffeeGenerator.this.next().
}
public void removeO { // He реализован
throw new UnsupportedOperationExceptionO;
}
}:
public Iterator
}
public static void main(String[] args) {
CoffeeGenerator gen = new CoffeeGenerator(); for (int i =0. i <5; i++)
System.out println(gen.nextO); for(Coffee с : new CoffeeGenerator(5)) System.out println(c),
}
} /* Output-Americano 0 Latte 1
Americano 2
Mocha 3 Mocha 4 Breve 5 Americano 6 Latte 7 Cappuccino 8 Cappuccino 9 *///:-
Параметризованный интерфейс Generator гарантирует, что next() вернет параметр типа. CoffeeGenerator также реализует интерфейс Iterable и поэтому может использоваться в синтаксисе foreach. Аргумент, по которому определяется момент прекращения перебора, передается при вызове второго конструктора.
А вот как выглядит другая реализация Generator
//. generics/Fibonacci java // Построение чисел Фибоначчи import net mindview util *;
public class Fibonacci implements Generator
public Integer nextO { return fib(count++); } private int fibCint n) {
if(n < 2) return 1, return fib(n-2) + fib(n-l),
}
public static void main(String[] args) { Fibonacci gen = new Fibonacci(); for(int i = 0; i < 18: i++)
System.out.print(gen.nextО + " ");
}
} /* Output-
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 *///:-
Хотя и внутри, и снаружи класса мы работаем с int, в параметре типа передается Integer. В этом проявляется одно из ограничений параметризации в языке Java: примитивные типы не могут использоваться в качестве параметров типа. Впрочем, в Java SE5 была добавлена удобная автоматическая упаковка (распаковка) для перехода от примитивных типов к объектным «оберткам», и наоборот.
Можно сделать следующий шаг вперед и создать генератор чисел Фибоначчи с реализацией Iterable. Конечно, можно изменить реализацию класса и добавить интерфейс Iterable, но исходные коды не всегда находятся в вашем распоряжении, и вообще там, где это возможно, лучше обойтись без их модификации. Вместо этого мы воспользуемся
Существует несколько вариантов реализации адаптеров. Например, для получения адаптируемого класса можно воспользоваться наследованием:
//: generi cs/IterableFi bonacci.java
// Adapt the Fibonacci class to make it Iterable.
import java.util.*;
public class IterableFibonacci
extends Fibonacci implements Iterable
public IterableFibonacci(int count) { n = count; } public Iterator
return new Iterator
public boolean hasNextO { return n > 0; } public Integer next О { n- -;
return Iterabl eFibonacci .this nextO.
}
public void removeO { // He реализован
throw new UnsupportedOperationExceptionO;
}
}:
}
public static void main(String[] args) {
for(int i . new IterableFibonacci(18)) System out printO + " ");
}
} /* Output-
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584
*///.-
Для использования IterableFibonacci в синтаксисе foreach мы передаем конструктору границу, чтобы метод hasNext() знал, когда следует возвращать false.
Параметризованные методы
До настоящего момента мы рассматривали параметризацию целых классов, однако параметризация может применяться и к отдельным методам классов. Сам класс при этом может быть параметризованным, а может и не быть — это не зависит от наличия параметризованных методов.
Параметризованный метод может изменяться независимо от класса. В общем случае параметризованные методы следует использовать «по мере возможности». Иначе говоря, если возможно параметризовать метод вместо целого класса, вероятно, стоит выбрать именно этот вариант. Кроме того, статические методы не имеют доступа к параметрам типа параметризованных классов; если такие методы должны использовать параметризацию, это должно происходить на уровне метода, а не на уровне класса.
Чтобы определить параметризованный метод, следует указать список параметров перед возвращаемым значением:
//• generics/GenericMethods.java
public class GenericMethods { public
System out println(x.getClass().getNameO);
}
public static void main(String[] args) {
GenericMethods gm = new GenericMethodsО,
gm.f("");
gm f(l); gm.f(l.O); gm.f(l.OF); gm f('c'); gm.f(gm);
}
} /* Output: java.lang.String java.lang Integer java.lang.Double java.lang.Float java.lang.Character GenericMethods *///:-
Класс GenericMethods не параметризован, хотя и класс, и его методы могут быть параметризованными одновременно. Но в данном случае только метод f() имеет параметр типа, обозначаемый списком параметров перед возвращаемым значением метода.