【问题标题】:Java8 - Functional Interface, Lambda and Method ReferenceJava8 - 函数式接口、Lambda 和方法参考
【发布时间】:2020-05-10 11:41:14
【问题描述】:

我有以下代码

   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 方法中使用方法引用来获得与 perform 方法中相似的结果。我尝试在 perform1 中使用像 Integer::parseInt 这样的方法引用,但它不起作用。如何对方法引用执行相同操作?为什么方法引用会出错?

【问题讨论】:

  • 你试过unchecked((FunctionThatThrows&lt;String, Integer&gt;) Integer::parseInt).apply("abc")吗?哪一种方式不起作用?
  • @Naman 这行得通。为什么需要显式类型转换?
  • 有多少个parseInt 可能与您的Integer::parseInt 匹配?当你转换时,你明确告诉编译器 which parseInt 使用
  • 我认为我们使用 java.lang.Integer 中的 parseInt 非常明确。为什么会模棱两可?
  • 我不知道为什么编译器没有选择正确的方法,但这是一个与实际相关的问题吗?我的意思是,在现实生活中你会使用结果,比如Function&lt;String,Integer&gt; f = unchecked(Integer::parseInt);...

标签: generics lambda java-8 method-reference functional-interface


【解决方案1】:

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

你不能,除非存在显式类型。由于unchecked 方法使用泛型参数FunctionThatThrows&lt;T, R&gt;,编译器不知道这些泛型类型TR 是什么。以下将无法编译:

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

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

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

  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
    

    (注意@Holgercomments也带来了这个)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 2017-08-28
    • 2019-07-25
    • 1970-01-01
    相关资源
    最近更新 更多