【问题标题】:Throwing exception from lambda [duplicate]从lambda抛出异常[重复]
【发布时间】:2015-10-16 17:47:37
【问题描述】:

鉴于此 java 8 代码

public Server send(String message) {
    sessions.parallelStream()
        .map(Session::getBasicRemote)
        .forEach(basic -> {
          try {
            basic.sendText(message);
          } catch (IOException e) {
            e.printStackTrace();
          }
        });

    return this;
}

我们如何正确地将这个IOException 委派到方法调用的堆栈上? (简而言之如何让这个方法抛出这个IOException?)

java 中的 Lambdas 看起来对错误处理不是很友好......

【问题讨论】:

    标签: java error-handling lambda java-8 checked-exceptions


    【解决方案1】:

    我的方法是偷偷地从 lambda 中抛出它,但要注意让 send 方法在其 throws 子句中声明它。使用ExceptionalI posted here

    public Server send(String message) throws IOException {
      sessions.parallelStream()
              .map(Session::getBasicRemote)
              .forEach(basic -> Exceptional.from(() -> basic.sendText(message)).get());
      return this;
    }
    

    通过这种方式,您可以有效地让编译器稍微“移开视线”,在代码中的某个位置禁用其异常检查,但是通过在 send 方法上声明异常,您可以恢复正常行为它的所有调用者。

    【讨论】:

    • 哦,现在我喜欢这样。这确实是很偷偷摸摸的。
    【解决方案2】:

    wrote an extension 到 Stream API,它允许抛出检查的异常。

    public Server send(String message) throws IOException {
        ThrowingStream.of(sessions, IOException.class)
            .parallelStream()
            .map(Session::getBasicRemote)
            .forEach(basic -> basic.sendText(message));
    
        return this;
    }
    

    【讨论】:

    • 谢谢,现在这是一个非常好的界面 :) 一定会检查你的源代码
    【解决方案3】:

    问题确实是所有在 lambdas 中使用的@FunctionalInterfaces 都不允许抛出异常,除了未经检查的异常。

    一种解决方案是使用a package of mine;有了它,您的代码可以读取:

    sessions.parallelStream()
        .map(Session::getBasicRemote)
        .forEach(Throwing.consumer(basic -> basic.sendText(message)));
    return this;
    

    【讨论】:

    • 那如何让send 抛出异常?
    • @MarkoTopolnik:我明白这一点。但是要让send 抛出IOException,还需要很多 的工作。如果我没记错的话,你基本上必须抓住ThrownByLambdaException,然后有一系列instanceof 来找出实际的异常是什么,这样你就可以重新抛出它。对于一两个例外情况可能还不错,但仍然非常冗长。
    • @T.J.Crowder 为了公平对待我们的同事 fge(正如你在我们的聊天中发现的那样),throwing-lambdas 确实支持偷偷摸摸的投掷成语。
    • @MarkoTopolnik:尽管据我所知,上面并没有真正使用它,也没有解释(例如,如果它确实使用了偷偷摸摸的投掷,throws decl. on send 是必不可少的,编译器不会强迫你添加它)。
    猜你喜欢
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多