Java 8:Lambda流,按异常方法过滤 [英] Java 8: Lambda-Streams, Filter by Method with Exception

查看:165
本文介绍了Java 8:Lambda流,按异常方法过滤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题,尝试使用Java 8的Lambda表达式。
通常它工作正常,但现在我有方法抛出$ $ $ $ $ $ $ $ $ $ $ $ $
最好看看下列代码:

I have a problem trying out the Lambda expressions of Java 8. Usually it works fine, but now I have methods that throw IOException's. It's best if you look at the following code:

class Bank{
    ....
    public Set<String> getActiveAccountNumbers() throws IOException {
        Stream<Account> s =  accounts.values().stream();
        s = s.filter(a -> a.isActive());
        Stream<String> ss = s.map(a -> a.getNumber());
        return ss.collect(Collectors.toSet());
    }
    ....
}

interface Account{
    ....
    boolean isActive() throws IOException;
    String getNumber() throws IOException;
    ....
}

问题是,它不编译,因为我必须捕获可能的异常的isActive和getNumber方法。但即使我明确使用try-catch-block,如下所示,它仍然不能编译,因为我没有捕获异常。所以JDK中有一个bug,或者我不知道如何捕获这些异常。

The problem is, it doesn't compile, because I have to catch the possible exceptions of the isActive- and the getNumber-Methods. But even if I explicitly use a try-catch-Block like below, it still doesn't compile because I don't catch the Exception. So either there is a bug in JDK, or I don't know how to catch these Exceptions.

class Bank{
    ....
    //Doesn't compile either
    public Set<String> getActiveAccountNumbers() throws IOException {
        try{
            Stream<Account> s =  accounts.values().stream();
            s = s.filter(a -> a.isActive());
            Stream<String> ss = s.map(a -> a.getNumber());
            return ss.collect(Collectors.toSet());
        }catch(IOException ex){
        }
    }
    ....
}

我该如何让它工作?有人可以提示我正确的解决方案吗?

How can I get it work? Can someone hint me to the right solution?

推荐答案

你必须在之前捕获例外, lambda:

You must catch the exception before it escapes the lambda:

s = s.filter(a -> { try { return a.isActive(); } 
                    catch (IOException e) { throw new UncheckedIOException(e); }}});

考虑到这个事实,即lambda不是在你写的地方进行评估,而是在一些完全不相关的地方,在JDK类中。所以这将是抛出被检查异常的点,并且在那个地方它不被声明。

Consider the fact that the lambda isn't evaluated at the place you write it, but at some completely unrelated place, within a JDK class. So that would be the point where that checked exception would be thrown, and at that place it isn't declared.

是的,检查的异常一直是一个痛苦,现在使用了性感和简洁的lambda语法,他们会破坏程序流程更糟糕。

Yes, checked exceptions have always been a pain, and now with the sexy and concise lambda syntax, they disrupt the program flow even worse.

在我的项目中,我处理这个问题无包装;相反,我使用一种有效地使编译器检查异常的方法。不用说,这应该谨慎处理,项目中的每个人都必须注意,检查的异常可能会在未声明的地方出现。这是管道代码:

In my projects I deal with this issue without wrapping; instead I use a method which effectively defuses compiler's checking of exceptions. Needless to say, this should be handled with care and everybody on the project must be aware that a checked exception may appear where it is not declared. This is the plumbing code:

public static <T> T uncheckCall(Callable<T> callable) {
  try { return callable.call(); }
  catch (Exception e) { return sneakyThrow(e); }
}
public static void uncheckRun(RunnableExc r) {
  try { r.run(); } catch (Exception e) { sneakyThrow(e); }
}
public interface RunnableExc { void run() throws Exception; }


public static <T> T sneakyThrow(Throwable e) {
  return Util.<RuntimeException, T>sneakyThrow0(e);
}
private static <E extends Throwable, T> T sneakyThrow0(Throwable t) throws E { throw (E)t; }

您的示例将被写为

return s.filter(a -> uncheckCall(a::isActive))
        .map(Account::getNumber)
        .collect(toSet());

,您可以期望获得一个 IOException 扔在你的脸上,尽管收集不声明它。在大多数情况下,但不是全部现实生活中的情况,您只想重新启动异常,无论如何,将其视为通用故障。在所有这些情况下,在清晰或正确的情况下都不会失去意义。只要注意其他情况,您实际上会想要对现场的异常做出反应。开发人员不会被编译器所知道,有一个 IOException 来抓住那里,编译器实际上会抱怨,如果你试图抓住它,因为我们已经把它愚弄了认为不会抛出这样的异常。

and you can expect to get an IOException thrown in your face, even though collect does not declare it. In most, but not all real-life cases you would want to just rethrow the exception, anyway, and handle it as a generic failure. In all those cases, nothing is lost in clarity or correctness. Just beware of those other cases, where you would actually want to react to the exception on the spot. The developer will not be made aware by the compiler that there is an IOException to catch there and the compiler will in fact complain if you try to catch it because we have fooled it into believing that no such exception can be thrown.

这篇关于Java 8:Lambda流,按异常方法过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆