Допустим, у меня есть следующий функциональный интерфейс в Java 8:
interface Action<T, U> {
U execute(T t);
}
А в некоторых случаях мне нужно действие без аргументов или возвращаемого типа. Поэтому я пишу что-то вроде этого:
Action<Void, Void> a = () -> { System.out.println("Do nothing!"); };
Тем не менее, это дает мне ошибку компиляции, мне нужно записать это как
Action<Void, Void> a = (Void v) -> { System.out.println("Do nothing!"); return null;};
Что некрасиво. Есть ли способ избавиться от Void
параметра типа?
Runnable
, что вы ищетеRunnable r = () -> System.out.println("Do nothing!");
Ответы:
Синтаксис, который вам нужен, возможен с помощью небольшой вспомогательной функции, которая преобразует
Runnable
вAction<Void, Void>
(например, вы можете поместить его вAction
):источник
@FunctionalInterface
. Он просто говорит, что это невозможно продлить ...Runnable
действия следует использовать пользовательское@FunctionalInterface
что-то под названиемSideEffect
, 2. Необходимость такой вспомогательной функции подчеркивает, что происходит что-то странное и, возможно, абстракция нарушена.Используйте,
Supplier
если это ничего не берет, но возвращает что-то.Используйте,
Consumer
если оно что-то берет, но ничего не возвращает.Используйте,
Callable
если он возвращает результат и может сгенерировать (наиболее похоже наThunk
общие термины CS).Используйте,
Runnable
если это не делает ни один и не может бросить.источник
public static void wrapCall(Runnable r) { r.run(); }
. СпасибоЛямбда:
на самом деле представляет собой реализацию для интерфейса, как:
который полностью отличается от того, который вы определили. Вот почему вы получаете ошибку.
Так как вы не можете продлить
@FunctionalInterface
или представить новый, я думаю, у вас не так много вариантов. Вы можете использоватьOptional<T>
интерфейсы, чтобы указать, что некоторые значения (возвращаемый тип или параметр метода) отсутствуют. Однако это не сделает лямбда-тело более простым.источник
Something
функция не может быть подтипом моегоAction
типа, и у меня не может быть двух разных типов.Вы можете создать подчиненный интерфейс для этого особого случая:
Он использует метод по умолчанию для переопределения унаследованного параметризованного метода
Void execute(Void)
, делегируя вызов более простому методуvoid execute()
.В результате гораздо проще использовать:
источник
Action<T, U>
объявлено в вопросе .....Я думаю, что эта таблица короткая и полезная:
Как сказано в других ответах, подходящим вариантом для этой проблемы является
Runnable
источник
Это невозможно. Функция, которая имеет тип возврата не void (даже если он есть
Void
), должна возвращать значение. Однако вы можете добавить статические методы,Action
что позволит вам «создать»Action
:Это позволит вам написать следующее:
источник
Добавьте статический метод в ваш функциональный интерфейс
Вывод
источник
Я не думаю, что это возможно, потому что определения функций не совпадают в вашем примере.
Ваше лямбда-выражение оценивается точно так же, как
тогда как ваша декларация выглядит
Например, если у вас есть следующий интерфейс
единственный вид функции (при создании экземпляра), который будет совместим, выглядит
и отсутствие оператора возврата или аргумента приведет к ошибке компилятора.
Поэтому, если вы объявляете функцию, которая принимает аргумент и возвращает его, я думаю, что невозможно преобразовать ее в функцию, которая не выполняет ни одного из упомянутых выше.
источник
Просто для справки, какой функциональный интерфейс может быть использован для ссылки на метод в случаях, когда метод вызывает и / или возвращает значение.
источник