在维护 foreach 语法糖的同时,有什么方法可以处理 - 并继续 - 迭代器中的异常?
没有这种糖。
有时行在语法上是虚假的,但这并不一定意味着我们不应该继续阅读文件。
好吧,如果不是那么异常,那么这些行都是假的,为什么要抛出异常呢?您可以稍微修改一下迭代器。假设您当前遍历 ParsedThingy 实例,并且如果解析失败,解析器将抛出 ThingyParseException,请遍历允许您查询解析结果的包装器,如下所示:
for (Possibly<ParsedThingy, ThingyParseException> p : parser) {
if (p.exception() != null) handleException(p.exception());
else doSomethingExcitingWith(p.value());
}
比看似自发返回nulls 更自我记录;它还允许您向客户端代码提供有关错误的信息。
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);
}
}
};
}
有点冗长,可以通过减少通用性来避免。