为什么一个方法引用ctor"抛出"......抛出?

Gho*_*ica 19 java constructor method-reference

我正在寻找一种优雅的方式来创建一个依赖注入工厂.在我的例子中,工厂只需要调用一个参数构造函数.我发现这个答案概述了如何将a Function<ParamType, ClassToNew>用于此类目的.

但我的问题是:在我的情况下,我的ctor声明抛出一些检查异常.

我没有得到:使用对该构造函数的方法引用创建该函数不起作用.如:

import java.util.function.Function;

public class Mcve {        
    public Mcve(String s) throws Exception {
        // whatever
    }        
    public static void main(String[] args) {
        Function<String, Mcve> mcveFactory = Mcve::new;
    }
}
Run Code Online (Sandbox Code Playgroud)

告诉我"未处理的异常:java.lang.Exception" Mcve::new.虽然这段代码没有调用构造函数.

两个问题:

  • 为什么那个错误?上面的代码没有调用ctor(还)?
  • 有没有优雅的方法来解决这个难题?(只需添加throws Exception到我main()没有帮助)

luk*_*302 23

您需要提供一个自定义接口ThrowingFunction,该接口有一个抛出的方法Exception.

public interface ThrowingFunction<ParameterType, ReturnType> {
    ReturnType invoke(ParameterType p) throws Exception;
}

public class Mcve {
    public Mcve(String s) throws Exception {
        // whatever
    }
    public static void main(String[] args) {
        ThrowingFunction<String, Mcve> mcveFactory = Mcve::new;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用此方法会导致调用mcveFactory.invoke("lalala");强制您处理构造函数抛出的异常.

错误的原因是您要存储的实际函数引用(不是100%确定术语)会引发异常,因此类型根本不匹配.如果你可以存储Mcve::new在一个函数内,那么调用该函数的人不再知道Exception可以抛出一个函数.如果实际抛出异常会怎么样?抛出异常并丢弃它都不起作用.


替代方案:如果您Function<String, Mcve>最终需要实际检索a ,那么您需要编写一个调用构造函数的函数(或lambda),捕获异常并将其丢弃或重新抛出包装在未选中的内容中RuntimeException.

public class Mcve {
    public Mcve(String s) throws Exception {
        // whatever
    }

    public static void main(String[] args) {
        Function<String, Mcve> mcveFactory = parameter -> {
            try {
                return new Mcve(parameter);
            } catch (Exception e) {
                throw new RuntimeException(e); // or ignore
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为错误消息本身至少有点误导,因为你通常在实际调用方法时会看到它.我当然可以理解导致第一个子问题的混乱.更清楚(遗憾的是不可能)陈述类似的东西

不兼容的类型Function<String,Mcve>Function<String,Mcve> throws Exception.