将多个语句中的异常收集到一个中

问题描述 投票:0回答:1

我正在编写一个管理器来使用

javax.mail
库处理发送电子邮件。构建
Message
时,我使用方法调用者提供的值多次调用
set
方法:

// MailBuilder: builder class for containing various email-related values
public void sendEmails(MailBuilder mailBuilder) {
  Message msg = new SMTPMessage(Session.getInstance(presetProperties));
  
  try {
    msg.setContent(mailBuilder.body);
    msg.setRecipients(RecipientType.TO, mailBuilder.to);
    msg.setRecipients(RecipientType.CC, mailBuilder.cc);
    msg.setRecipients(RecipientType.BCC, mailBuilder.bcc);
    msg.setSubject(mailBuilder.subject);
  } catch (MessagingException e) {
    throw new IllegalArgumentException("Malformed email", e);
  }

  // ...send email
}

如果任何

set
方法抛出异常,我想将其包装在
IllegalArgumentException
中以发送给调用者。但是,如果我将它们全部包装在一个
try
块中,如果
setContent
抛出异常,则不会调用其他方法,并且这些方法可能发生的任何错误也不会传达给调用者。我知道我可以像这样将 try-catch 块链接在一起来收集可能被抑制的异常,但它非常笨重:

MessagingException collectedExceptions = null;
try {
  msg.setContent(mailBuilder.body)
} catch (MessagingException e) {
  if (collectedExceptions == null) collectedExceptions = e;
  else collectedExceptions.addSuppressed(e);
}

try {
  msg.setSubject(mailBuilder.subject);
} catch (MessagingException e) {
  if (collectedExceptions == null) collectedExceptions = e;
  else collectedExceptions.addSuppressed(e);
}

// repeat for other methods

if (collectedExceptions != null) throw collectedExceptions;

是否有一种更简洁的方法来使用多个方法,并且仅在任意数量的方法末尾抛出异常?

java exception
1个回答
0
投票

我不知道为什么你需要调用每一个方法,即使一个方法失败了。至于你的问题,看来你担心的是太多的样板文件。一种解决方案是将您的 try-catch 委托给另一个方法并传递一个列表来收集异常。这是一个例子:

public void sendEmails(MailBuilder mailBuilder) {
    Message msg = new SMTPMessage(Session.getInstance(presetProperties));
    List<Throwable> exceptions = new ArrayList<Throwable>(5);

    tryInvoke(() -> msg.setContent(mailBuilder.body), exceptions);
    tryInvoke(() -> msg.setRecipients(RecipientType.TO, mailBuilder.to), exceptions);
    tryInvoke(() -> msg.setRecipients(RecipientType.CC, mailBuilder.cc), exceptions);
    tryInvoke(() -> msg.setRecipients(RecipientType.BCC, mailBuilder.bcc), exceptions);
    tryInvoke(() -> msg.setSubject(mailBuilder.subject), exceptions);

    if (!exceptions.isEmpty())
        throw new IllegalArgumentException(
                exceptions.stream().map(Throwable::getMessage).collect(Collectors.joining(", ")));
}

public static void tryInvoke(ThrowingRunnable<?> callable, List<Throwable> exceptions) {
    try {
        callable.run();
    } catch (Throwable e) {
        exceptions.add(e);
    }
}

@FunctionalInterface
public interface ThrowingRunnable<E extends Throwable> {
    void run() throws E;
}
© www.soinside.com 2019 - 2024. All rights reserved.