Есть ли способ обработки - и продолжения - исключения в итераторе при сохранении синтаксического сахара foreach?
Нет такого сахара.
Иногда строки будут синтаксически поддельными, но это не обязательно означает, что мы не должны продолжать чтение файла.
Ну, если это не так, что исключительные строки являются поддельными, зачем создавать исключения? Вы могли бы немного переделать свой итератор. Предполагая, что вы в настоящее время итерируете по ParsedThingy
экземплярам, и что анализатор выдает ThingyParseException
в случае сбоя синтаксического анализа, итерируйте по оболочкам, которые позволяют запрашивать результаты разбора для поддельности, например:
for (Possibly<ParsedThingy, ThingyParseException> p : parser) {
if (p.exception() != null) handleException(p.exception());
else doSomethingExcitingWith(p.value());
}
Несколько более самодокументируемый, чем, казалось бы, самопроизвольно возвращающийся null
с; он также позволяет передавать информацию об ошибке клиентскому коду.
Possibly<V, X>
- это обертка вокруг значения, которое на самом деле может быть исключением. Вы можете запросить исключительный статус, проверив, является ли exception()
ненулевым, и получить значение для неисключительного случая, вызвав value()
(который выдаст, если это исключение):
class Possibly<V, X extends Throwable> {
private final V value;
private final X exception;
public static <V, X extends Throwable> Possibly<V, X> forValue(V v){
return new Possibly<V, X>(v, null);
}
public static <V, X extends Throwable> Possibly<V, X> forException(X x){
if (x == null) throw new NullPointerException();
return new Possibly<V, X>(null, x);
}
private Possibly(V v, X x){ value = v; exception = x; }
public X exception(){ return exception; }
public V value() throws X {
if (exception != null) throw exception;
return value;
}
}
Тогда ваш iterator()
будет выглядеть примерно так:
Iterator<Possibly<ParsedThingy, ThingyParseException>> parse() {
return new Iterator<Possibly<ParsedThingy, ThingyParseException>> {
public boolean hasNext(){ ... }
public void remove(){ ... }
public Possibly<ParsedThingy, ThingyParseException> next()
try {
ParsedThingy t = parseNext(); // throws ThingyParseException
return Possibly.forValue(t);
} catch (ThingyParseException e) {
return Possibly.forException(e);
}
}
};
}
Вид многословия, можно было бы избежать, сделав материал менее общим.