Альтернативный способ кодировать несколько проверок для NullPointerException, JAVA 8 - PullRequest
0 голосов
/ 01 сентября 2018

Есть ли лучший способ кодировать это в JAVA 8?

    if (info1 != null && info1.getId() != null && info1.getPartyNumber()!= null) {
        billing.setSenderId(info1.getId());
        billing.setSenderNumber(info1.getPartyNumber());
    }
    if (info2 != null && info2.getId() != null && info2.getPartyNumber()!= null) {
        billing.setReceiverId(info2.getId());
        billing.setSellerNumber(info2.getPartyNumber());            
    }

    ..
    ..

Спасибо заранее. Примечание: я изучил Optional.ofNullable(), но не уверен, что это действительно может помочь с несколькими проверками?

Ответы [ 4 ]

0 голосов
/ 01 сентября 2018

Если ваши несколько повторений следуют точному шаблону (например, каждое нечетное повторение устанавливает receiver, иначе sender), или этот шаблон может быть извлечен в Set<Integer>, вы можете использовать Map<Integer, Info>, где ключ является Идентификатор Info, выполнить итерацию по нему и установить только выбранные элементы.

List<Info> list = ...                                             // List of Info
Map<Integer, Info> map = list.stream()                            // Stream
    .filter(Objects::nonNull)                                     // Filter null values
    .filter(i -> i.getId() != null && i.getPartyNumber() != null) // Filter null fields
    .collect(Collectors.toMap(Info::getId, i -> i));              // Collect to Map<Integer, Info>

for (int i=0; i<10; i++) {                                        // The number of repetitions
    if (map.containsKey(i)) {                                     // If the ID was not filtered
        Info info = map.get(i);                                   // Get the Info
                                                                  // Here the pattern comes
        if (i % 2 == 0) {                                         // you can either compare with a
                                                                  // predefined Set of IDs
            billing.setSenderId(info.getId());                    
            billing.setSenderNumber(info.getPartyNumber());       // Sender
        } else { 
            billing.setReceiverId(info.getId());                  // Receiver
            billing.setSellerNumber(info.getPartyNumber());          
        }
    }
}

Решение будет различным и зависит от количества возможных настроек наряду с sender и receiver. Кроме того, расчет паттерна может быть основан на другой логике - я рекомендую проверить по ex. Set<Integer> senders, который будет содержать идентификаторы, подходящие для установки в качестве отправителя, то же самое относится и к получателю и другим возможностям.

  • За :
    • Независимо от количества повторений Info длина решения остается неизменной (за исключением сбора всех Info s для ввода list).
    • Позволяет избежать раздувания кода и повторений.
  • Против :
    • Вы должны продумать расчет и логику, чтобы определить, что нужно установить.
    • Может выглядеть грязно и трудно для чтения.
0 голосов
/ 01 сентября 2018

Если вы хотите переписать его с Optional, это может выглядеть так:

Optional.ofNullable(info1)
.filter(i -> i.getId() != null)
.filter(i -> i.getPartyNumber() != null)
.ifPresent(i -> {
  billing.setSenderId(info1.getId());
  billing.setSenderNumber(info1.getPartyNumber());
});

Редактировать

Мы обрабатываем info1, только если это не null и все условия, указанные как Optional.filter параметры совпадают. Таким образом, только в случае info1 != null и info1.getId() != null и info1.getPartyNumber() != null будет выполняться Consumer. Это альтернативный способ кодирования нескольких проверок . Он делает то, что делает ваш код.

То же самое относится и к info2.

Редактировать

Свободный API Optional в сочетании с многострочным обозначением разбивает каждое условие на собственную строку. ИМО делает код легким для чтения и, следовательно, легким для понимания Он сохраняет простоту, ясность исходного кода в максимально возможной степени и все еще ведет себя так же.

0 голосов
/ 01 сентября 2018

Если вы копируете код в своем источнике, вы всегда должны думать дважды. Я думаю, что ваше тестирование в порядке, но я бы сделал для него метод, поэтому ваш код выглядит так:

if (isComplete (info1) { .... } if (isComplete (info2) { .... }

0 голосов
/ 01 сентября 2018

Вот лучшее, что я мог придумать. Я дам вам решить, будет ли он чище или нет:

Optional<Info> oInfo1 = Optional.ofNullable(info1);
oInfo1.map(Info::getId).ifPresent(billing::setSenderId);
oInfo1.map(Info::getPartyNumber).ifPresent(billing::setSenderNumber);

Optional<Info> oInfo2 = Optional.ofNullable(info2);
oInfo2.map(Info::getId).ifPresent(billing::setReceiverId);
oInfo2.map(Info::getPartyNumber).ifPresent(billing::setSellerNumber);

Обратите внимание, что это немного отличается от оригинала тем, что может установить одно поле, даже если другое значение равно нулю.

...