Лучший способ продолжить после исключений в Java - PullRequest
0 голосов
/ 06 ноября 2018

Предполагая, что мне нужно прочитать файл, а затем создать из него объект 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

Вопрос:

Есть ли лучший способ сделать это, чтобы избежать повторения? Функциональный стиль может быть?

а) Какой лучший подход, если я не могу изменить PersonData класс.
б) Какой лучший подход, если я могу переписать PersonData класс.

Ответы [ 3 ]

0 голосов
/ 06 ноября 2018

Вы также можете использовать решение, предусмотренное этим: https://stackoverflow.com/a/28659553/6648303

Это решение не будет жаловаться на этапе компиляции на проверенные исключения. Было бы что-то вроде этого:

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()));
...
0 голосов
/ 06 ноября 2018

Учитывая ваше текущее объявление, я бы сделал это следующим образом.

Определите @FunctionalInterface, которому вы можете передать свою логику ввода / вывода:

@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 или нет.

0 голосов
/ 06 ноября 2018

Если вы используете 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);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...