如何在 Java8 中为 void(非 Void)方法指定函数类型?

2024-04-08

我正在研究 Java 8,以了解如何发挥一等公民的作用。我有以下片段:

package test;

import java.util.*;
import java.util.function.*;

public class Test {

    public static void myForEach(List<Integer> list, Function<Integer, Void> myFunction) {
      list.forEach(functionToBlock(myFunction));
    }

    public static void displayInt(Integer i) {
      System.out.println(i);
    }


    public static void main(String[] args) {
      List<Integer> theList = new ArrayList<>();
      theList.add(1);
      theList.add(2);
      theList.add(3);
      theList.add(4);
      theList.add(5);
      theList.add(6);
      myForEach(theList, Test::displayInt);
    }
}

我想做的是传递方法displayInt到方法myForEach使用方法参考。编译器会产生以下错误:

src/test/Test.java:9: error: cannot find symbol
      list.forEach(functionToBlock(myFunction));
                   ^
  symbol:   method functionToBlock(Function<Integer,Void>)
  location: class Test
src/test/Test.java:25: error: method myForEach in class Test cannot be applied to given ty
pes;
      myForEach(theList, Test::displayInt);
      ^
  required: List<Integer>,Function<Integer,Void>
  found: List<Integer>,Test::displayInt
  reason: argument mismatch; bad return type in method reference
      void cannot be converted to Void

编译器抱怨说void cannot be converted to Void。我不知道如何在签名中指定函数接口的类型myForEach这样代码就可以编译了。我知道我可以简单地更改返回类型displayInt to Void然后返回null。但是,在某些情况下,可能无法更改我想要传递到其他地方的方法。有没有简单的方法可以重复使用displayInt是这样吗?


您尝试使用错误的接口类型。方式Function https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html在这种情况下不合适,因为它接收一个参数并有一个返回值。相反,你应该使用Consumer https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html(以前称为块)

函数类型声明为

interface Function<T,R> {
  R apply(T t);
}

但是, Consumer 类型与您正在寻找的类型兼容:

interface Consumer<T> {
   void accept(T t);
}

因此,Consumer 与接收 T 且不返回任何内容 (void) 的方法兼容。这就是你想要的。

例如,如果我想显示列表中的所有元素,我可以简单地使用 lambda 表达式为其创建一个使用者:

List<String> allJedi = asList("Luke","Obiwan","Quigon");
allJedi.forEach( jedi -> System.out.println(jedi) );

您可以在上面看到,在这种情况下,lambda 表达式接收一个参数并且没有返回值。

现在,如果我想使用方法引用而不是 lambda 表达式来创建这种类型的消费,那么我需要一个接收 String 并返回 void 的方法,对吧?

我可以使用不同类型的方法引用,但在这种情况下,让我们通过使用println方法中的System.out对象,像这样:

Consumer<String> block = System.out::println

或者我可以简单地做

allJedi.forEach(System.out::println);

The println方法是合适的,因为它接收一个值并具有返回类型 void,就像accept消费者中的方法。

因此,在您的代码中,您需要将方法签名更改为类似:

public static void myForEach(List<Integer> list, Consumer<Integer> myBlock) {
   list.forEach(myBlock);
}

然后您应该能够在您的情况下使用静态方法引用创建一个消费者,方法是:

myForEach(theList, Test::displayInt);

最终,你甚至可以摆脱你的myForEach方法完全并且简单地执行:

theList.forEach(Test::displayInt);

关于一等公民的职能

总而言之,事实是 Java 8 不会拥有一等公民的函数,因为结构函数类型不会添加到该语言中。 Java 将提供一种替代方法来从 lambda 表达式和方法引用创建函数接口的实现。最终 lambda 表达式和方法引用将绑定到对象引用,因此我们拥有的只是作为一等公民的对象。重要的是功能是存在的,因为我们可以将对象作为参数传递,将它们绑定到变量引用并将它们作为其他方法的值返回,然后它们几乎具有类似的目的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Java8 中为 void(非 Void)方法指定函数类型? 的相关文章

随机推荐