抛出异常的Java 8 Lambda函数?

本文翻译自:Java 8 Lambda function that throws exception?

I know how to create a reference to a method that has a String parameter and returns an int , it's: 我知道如何创建对具有String参数并返回int的方法的引用,它是:

Function<String, Integer>

However, this doesn't work if the function throws an exception, say it's defined as: 但是,如果该函数引发异常,则将其定义为:

Integer myMethod(String s) throws IOException

How would I define this reference? 我将如何定义此参考?


#1楼

参考:https://stackoom.com/question/1EMAy/抛出异常的Java-Lambda函数


#2楼

Disclaimer: I haven't used Java 8 yet, only read about it. 免责声明:我还没有使用Java 8,只阅读过它。

Function<String, Integer> doesn't throw IOException , so you can't put any code in it that throws IOException . Function<String, Integer>不会引发IOException ,因此您不能在其中放入任何throws IOException代码。 If you're calling a method that expects a Function<String, Integer> , then the lambda that you pass to that method can't throw IOException , period. 如果调用的方法需要Function<String, Integer> ,则传递给该方法的lambda不能抛出IOException ,period。 You can either write a lambda like this (I think this is the lambda syntax, not sure): 您可以这样编写一个lambda(我不确定这是lambda语法):

(String s) -> {
    try {
        return myMethod(s);
    } catch (IOException ex) {
        throw new RuntimeException(ex);
        // (Or do something else with it...)
    }
}

Or, if the method you're passing the lambda to is one you wrote yourself, you can define a new functional interface and use that as the parameter type instead of Function<String, Integer> : 或者,如果将lambda传递给您的方法是您自己编写的,则可以定义一个新的函数接口,并将其用作参数类型,而不是Function<String, Integer>

public interface FunctionThatThrowsIOException<I, O> {
    O apply(I input) throws IOException;
}

#3楼

You'll need to do one of the following. 您需要执行以下操作之一。

  • If it's your code, then define your own functional interface that declares the checked exception: 如果是您的代码,请定义自己的函数接口,该接口声明已检查的异常:

     @FunctionalInterface public interface CheckedFunction<T, R> { R apply(T t) throws IOException; } 

    and use it: 并使用它:

     void foo (CheckedFunction f) { ... } 
  • Otherwise, wrap Integer myMethod(String s) in a method that doesn't declare a checked exception: 否则,将Integer myMethod(String s)包装在未声明检查异常的方法中:

     public Integer myWrappedMethod(String s) { try { return myMethod(s); } catch(IOException e) { throw new UncheckedIOException(e); } } 

    and then: 接着:

     Function<String, Integer> f = (String t) -> myWrappedMethod(t); 

    or: 要么:

     Function<String, Integer> f = (String t) -> { try { return myMethod(t); } catch(IOException e) { throw new UncheckedIOException(e); } }; 

#4楼

This is not specific to Java 8. You are trying to compile something equivalent to: 这不是特定于Java 8的。您尝试编译的内容等同于:

interface I {
    void m();
}
class C implements I {
    public void m() throws Exception {} //can't compile
}

#5楼

Another solution using a Function wrapper would be to return either an instance of a wrapper of your result, say Success, if everything went well, either an instance of, say Failure. 使用函数包装的另一种解决方案是,如果一切顺利,则返回结果包装的一个实例,即成功;如果失败,则返回一个实例。

Some code to clarify things : 一些代码来澄清事情:

public interface ThrowableFunction<A, B> {
    B apply(A a) throws Exception;
}

public abstract class Try<A> {

    public static boolean isSuccess(Try tryy) {
        return tryy instanceof Success;
    }

    public static <A, B> Function<A, Try<B>> tryOf(ThrowableFunction<A, B> function) {
        return a -> {
            try {
                B result = function.apply(a);
                return new Success<B>(result);
            } catch (Exception e) {
                return new Failure<>(e);
            }
        };
    }

    public abstract boolean isSuccess();

    public boolean isError() {
        return !isSuccess();
    }

    public abstract A getResult();

    public abstract Exception getError();
}

public class Success<A> extends Try<A> {

    private final A result;

    public Success(A result) {
        this.result = result;
    }

    @Override
    public boolean isSuccess() {
        return true;
    }

    @Override
    public A getResult() {
        return result;
    }

    @Override
    public Exception getError() {
        return new UnsupportedOperationException();
    }

    @Override
    public boolean equals(Object that) {
        if(!(that instanceof Success)) {
            return false;
        }
        return Objects.equal(result, ((Success) that).getResult());
    }
}

public class Failure<A> extends Try<A> {

    private final Exception exception;

    public Failure(Exception exception) {
        this.exception = exception;
    }

    @Override
    public boolean isSuccess() {
        return false;
    }

    @Override
    public A getResult() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Exception getError() {
        return exception;
    }
}

A simple use case : 一个简单的用例:

List<Try<Integer>> result = Lists.newArrayList(1, 2, 3).stream().
    map(Try.<Integer, Integer>tryOf(i -> someMethodThrowingAnException(i))).
    collect(Collectors.toList());

#6楼

What I'm doing is to allow the user to give the value he actually want in case of exception . 我正在做的是允许用户在异常情况下提供他实际想要的值。 So I've something looking like this 所以我看起来像这样

public static <T, R> Function<? super T, ? extends R> defaultIfThrows(FunctionThatThrows<? super T, ? extends R> delegate, R defaultValue) {
    return x -> {
        try {
            return delegate.apply(x);
        } catch (Throwable throwable) {
            return defaultValue;
        }
    };
}

@FunctionalInterface
public interface FunctionThatThrows<T, R> {
    R apply(T t) throws Throwable;
}

And this can then be call like : 然后可以这样调用:

defaultIfThrows(child -> child.getID(), null)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值