Как указать типы функций для методов void (не Void) в Java8?



я играю с 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 до Void а потом вернуться null. Однако могут возникнуть ситуации, когда невозможно изменить метод, который я хочу передать где-то еще. Есть ли простой способ повторного использования displayInt как это?

535   2  

2 ответов:

вы пытаетесь использовать неправильный тип интерфейса. Тип функции не подходит в этом случае, потому что он получает параметр и имеет возвращаемое значение. Вместо этого вы должны использовать потребитель (ранее известный как блок)

тип функции объявляется как

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

однако тип потребителя совместим с тем, что вы ищете:

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

как таковой, потребитель совместим с методами, которые получите T и ничего не возвращайте (void). И это то, что вы хотите.

например, если бы я хотел отобразить все элементы в списке, я мог бы просто создать для этого потребителя с лямбда-выражением:

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

вы можете видеть выше, что в этом случае лямбда-выражение получает параметр и не имеет возвращаемого значения.

теперь, если я хотел использовать ссылку на метод вместо лямбда-выражения для создания потребления этого типа, то мне нужен метод, который получает строку и возвращает void, верно?.

я мог бы использовать различные типы ссылок на методы, но в этом случае давайте воспользуемся ссылкой на метод объекта с помощью println метод

когда вам нужно принять функцию в качестве аргумента, который не принимает аргументов и не возвращает результата (void), на мой взгляд, все равно лучше иметь что-то вроде

  private interface Thunk { void apply(); }

где-то в коде. В моих курсах функционального программирования слово "thunk" использовалось для описания таких функций. Почему это не в java.утиль.функция находится за пределами моего понимания.

в других случаях я нахожу, что даже когда java.утиль.функция имеет что-то, что соответствует подписи, которую я хочу - это все еще не всегда правильно, когда имя интерфейса не соответствует использованию функции в моем коде. Я думаю, что это аналогичная точка зрения, которая сделана в другом месте здесь относительно "Runnable" - это термин, связанный с классом Thread - поэтому, хотя он может иметь подпись, которая мне нужна, это все еще, вероятно, смутит читателя.

Comments

    Ничего не найдено.