java 中出现异常后继续的更好方法

Better way to continue after exceptions in java

假设我必须从一个文件中读取,然后从中构造一个 java 对象。

PersonData p = new PersonData();
p.setName(readTokenAsString());
p.setAge(AgeConverter.createFromDateOfBirth(readTokenAsString()));  // this throws a checked exception if the date of birth is mal-formed.

//... a list of methods that throws exception as AgeConverter

我想要的行为:如果一个属性有问题,忽略它并继续处理其他属性。

我能想到的解决办法:

try {
  p.setAge1(...);
} catch (Exception e) {
  //log and ignore
}

try {
  p.setAge2(...);
} catch (Exception e) {
  //log and ignore
}

//repeat for each attribute

问题:

是否有更好的方法来避免重复?也许是功能风格?

a) 如果我无法修改 PersonData class.
,最好的方法是什么 b) 如果我可以重写 PersonData class,最好的方法是什么?

如果你使用 Java 8 你可以做这样的事情。使用一种抛出 Exception

的方法创建您自己的功能接口
public interface MyConsumer<T> {
    public void process(T t) throws Exception;
}

并创建一个 static 方法来使用该接口

public static <T> void setAndLogException(T value, MyConsumer<T> consumer) {
  try {
    consumer.process(value);
  } catch (Exception e) {
  // log exception
  }
}

然后像setAndLogException(AgeConverter.createFromDateOfBirth(readTokenAsString()), p::setAge);

一样使用它

你也可以使用这个提供的解决方案:

此解决方案不会在编译阶段抱怨已检查的异常。 它会是这样的:

public static void ignoringExc(RunnableExc r) {
  try { r.run(); } catch (Exception e) { }
}

@FunctionalInterface public interface RunnableExc { void run() throws Exception; }

然后:

PersonData p = new PersonData();
ignoringExc(() -> p.setName(readTokenAsString()));
...

鉴于您当前的声明,我将按如下方式进行。

定义一个 @FunctionalInterface,您可以向其传递 I/O 逻辑:

@FunctionalInterface
public interface CheckedSupplier<T> {
    T getValue() throws Exception;
}

定义一个使用 @FunctionaInterface:

的实用方法
public static final <T> T getValueWithDefault(CheckedSupplier<T> supplier, T defaultValue) {
    try {
        return supplier.getValue();
    } catch (Exception e){
        return defaultValue;
    }
}

使用实用方法如下:

PersonData p = new PersonData();
p.setName(getValueWithDefault(() -> readTokenAsString(), "default"));
p.setAge(getValueWithDefault(() -> AgeConverter.createFromDateOfBirth(readTokenAsString()), 0));

无论您是否要修改 PersonData class 天气,这都可以解决问题。