До сих пор мы имели дело только с итерациями по встроенным в Java классам и типам - массивам, спискам, отображениям, наборам и другим коллекциям. И хотя это хорошее дело, красота любого языка программирования заключается в возможности определять собственные классы.
Специализированные объекты составляют костяк любого масштабного приложения. В этом разделе это и рассматривается - концепции и действия по использованию ваших собственных объектов в конструкции for/in.
Для использования цикла for/in необходимо добавить еще один интерфейс - java.lang.Iterable.
package java.lang;
public interface Iterable { public java.util.Iterator iterator(); }
Для обеспечения возможности работы ваших классов или объектов в for/in необходимо реализовать интерфейс Iterable. Есть два основных сценария:
Расширить существующий класс коллекции, который уже реализует интерфейс Iterable (и, следовательно, уже поддерживает for/in).
Управлять итерацией вручную, определив свою собственную реализацию Iterable.
Пример:
import java.util.Iterator;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/**
* Этот класс предоставляет построчную итерацию по текстовому файлу.
* Метод итератора remove() генерирует UnsupportedOperatorException.
* Итератор перехватывает и генерирует IOExceptions как IllegalArgumentExceptions.
*/
public class TextFile implements Iterable<String> {
// Используется в TextFileIterator ниже
final String filename;
public TextFile(String filename) {
this.filename = filename;
}
// Это единственный метод интерфейса Iterable
public Iterator<String> iterator() {
return new TextFileIterator();
}
// Этот не статический класс является реализацией итератора
class TextFileIterator implements Iterator<String> {
// Поток для чтения
BufferedReader in;
// Возвращает значение следующего вызова next()
String nextline;
public TextFileIterator() {
// Открыть файл, прочитать и запомнить первую строку
// Выбрать строку наперед для использования функции hasNext()
try {
in = new BufferedReader(new FileReader(filename));
nextline = in.readLine();
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
// Если следующая строка не равна null, у нас есть следующая строка
public boolean hasNext() {
return nextline != null;
}
// Возвращает следующую строку, но сначала читает еще одну строку за ней
public String next() {
try {
String result = nextline;
// Если еще не достигли EOF ...
if (nextline != null) {
nextline = in.readLine(); // Читать еще одну строку
if (nextline == null)
in.close(); // Закрыть по достижению EOF
}
// Возвратить строку, прочитанную раннее
return result;
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
// Файл только для чтения, мы не разрешаем удаление строк
public void remove() {
throw new UnsupportedOperationException();
}
}
public static void main(String[] args) {
String filename = "TextFile.java";
if (args.length > 0)
filename = args[0];
for (String line : new TextFile(filename))
System.out.println(line);
}
}
Вопрос 1.
Для чего можно использовать реализацию интерфейса Iterable в создаваемых вами классах?