【问题标题】:Handling exception with lambda expression [duplicate]使用 lambda 表达式处理异常
【发布时间】:2017-03-16 16:25:39
【问题描述】:

我对 lambda 表达式有疑问。我的代码:

public static void main(String[] args) {

    Function<String, String> lambda = path -> {
        String result = null;
        try {
            BufferedReader br = new BufferedReader(new FileReader(path));
            String line;
            while ((line = br.readLine()) != null) {
                result = result + line;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    };
}

我现在正在尝试编写这样的代码:

public static void main(String[] args) throws IOException {

    Function<String, String> lambda = path -> {
        String result = null;
        BufferedReader br = new BufferedReader(new FileReader(path));
        String line;
        while ((line = br.readLine()) != null) {
            result = result + line;
        }
        return result;
    };
}

这可能吗?我只能使用 java.util.function。我尝试从“lambda”中删除 try catch,而我的“main”方法应该正在捕获该异常。

【问题讨论】:

  • 请注意,在您的第一个解决方案中,您永远不会关闭 BufferedRead,从而导致内存泄漏。

标签: java lambda exception-handling


【解决方案1】:

内置的Function 类不允许您抛出未经检查的异常,您可以从apply() method 的签名中看到。

但是,您可以轻松定义自己的 @FunctionalInterface,它允许抛出异常,例如:

@FunctionalInterface
public interface CheckedFunction<U,V> {
  public V apply(U u) throws Exception;
}

并将您的 lambda 变量改为 CheckedFunction


如果您出于某种原因必须使用内置的Function,另一种方法是将所有已检查的异常转换为RuntimeExceptions,例如:

Function<Foo,Bar> f = foo -> {
  try {
    return foo.methodThatCanThrow();
  } catch (RuntimeException e) {
    throw e;
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
};

这将允许您的代码编译,但肯定不是一般推荐的最佳做法。

【讨论】:

  • "我只能用java.util.function"
  • @MarkoTopolnik 为什么?这是什么无意义的限制?您不能从 java.util.function.Function 抛出异常,并且 lambdas 被设计以支持定义您自己的函数式接口。如果您想以在示例代码中使用 lambda 的方式使用它们,则需要使用不同的接口。
  • 看来你把我和 OP 搞混了。
【解决方案2】:

正如dimo414所说,先声明一个新的functional interface

@FunctionalInterface
public interface CheckedFunction<U, V> {
    public V apply(U u) throws IOException;
}

然后我会更进一步,将 lambda 表达式重构为以下内容:

CheckedFunction<String, String> lambda = path -> {
            try (BufferedReader br = new BufferedReader(new FileReader(path))) {
                return br.lines().collect(Collectors.joining());
            }
        };

try-with-resources 负责在任何情况下关闭BufferedRead 并使用stream API 的简洁性来连接所有行。

更进一步,如果您使用Files,您甚至不需要再为BufferedReader 操心了!这可以归结为以下 lambda:

CheckedFunction<String, String> lambda = path -> Files.lines(Paths.get(path)).collect(Collectors.joining());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 2014-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多