Java8-函数接口,Lambda和方法参考



我有以下代码

public class FunctionalInterfaceTest {
@FunctionalInterface
public interface FunctionThatThrows<T, R> {
R apply(T t) throws Exception;
}
public void perform() {
try {
unchecked((String x) -> Integer.parseInt(x)).apply("abc");
} catch (Exception e) {
System.out.println("Encountered exception" + e.getMessage());
}
}
public void perform1() {
try {
unchecked(<fill-in-here-using-method-reference>);
} catch (Exception e) {
System.out.println("Encountered Exception" + e.getMessage());
}
}
public <T, R> Function<T, R> unchecked(FunctionThatThrows<T, R> f) {
return (a) -> {
try {
return f.apply(a);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
public static void main(String[] args) {
FunctionalInterfaceTest test = new FunctionalInterfaceTest();
test.perform();
test.perform1();
}
}

我想在perform1方法中使用Method Reference来获得与perform方法类似的结果。我尝试在perform1中使用Integer::parseInt这样的方法引用,但它不起作用。如何对方法引用执行同样的操作?为什么方法引用会出错?

如何对方法引用执行同样的操作?为什么方法引用会出错?

您不能,除非存在显式类型。由于unchecked方法使用泛型参数FunctionThatThrows<T, R>,编译器不知道这些泛型类型TR是什么。以下内容不会编译:

unchecked(s -> Integer.parseInt(s));    // doesn't compile

编译器认为s是一个与Integer.parseInt(String s)方法不兼容的Object。这就是为什么它是模棱两可的。

重点是,必须明确说明泛型参数的类型。有三种方法可以定义类型并保留通用解决方案。

  1. 如前所述,使用下转换指定sString

    unchecked((String x) -> Integer.parseInt(x))                 // no method reference
    
  2. 对传递的lambda表达式使用显式强制转换。这个解决方案是IntelliJ Idea提供给我的第一个解决方案。现在很清楚,编译器对传递函数的输入和输出分别是StringInteger。请注意,此结构是Integer.parseInt(String s)所要求的`:

    unchecked((FunctionThatThrows<String, Integer>) Integer::parseInt); // with method reference
    
  3. 明确定义所需的返回类型:

    Function<String, Integer> f = unchecked((FunctionThatThrows<String, Integer>) Integer::parseInt);
    

    多余的铸造应该被省略,它给出了一个更明确的结果:

    Function<String, Integer> f = unchecked(Integer::parseInt);  // with method reference
    

    (注意@Holger在评论中也提到了这个(

最新更新