Załóżmy, że mam następujący interfejs funkcjonalny w Javie 8:
interface Action<T, U> {
U execute(T t);
}
A w niektórych przypadkach potrzebuję akcji bez argumentów lub typu zwracanego. Piszę więc coś takiego:
Action<Void, Void> a = () -> { System.out.println("Do nothing!"); };
Daje mi to jednak błąd kompilacji, muszę go zapisać jako
Action<Void, Void> a = (Void v) -> { System.out.println("Do nothing!"); return null;};
Co jest brzydkie. Czy jest jakiś sposób na pozbycie się Void
parametru type?
Runnable
tego, czego szukaszRunnable r = () -> System.out.println("Do nothing!");
Odpowiedzi:
Składnia, której szukasz, jest możliwa dzięki niewielkiej funkcji pomocniczej, która konwertuje a
Runnable
naAction<Void, Void>
(możesz to umieścićAction
na przykład):źródło
@FunctionalInterface
. Mówi jedynie, że nie można go przedłużyć ...Runnable
działania należy podjąć niestandardowe@FunctionalInterface
coś o nazwieSideEffect
, 2. potrzeba takiej funkcji pomocnika podkreśla, że dzieje się coś dziwnego i prawdopodobnie abstrakcja jest zepsuta.Użyj,
Supplier
jeśli nic nie bierze, ale coś zwraca.Użyj,
Consumer
jeśli coś zabiera, ale nic nie zwraca.Użyj,
Callable
jeśli zwróci wynik i może rzucić (najbardziej zbliżony doThunk
ogólnych warunków CS).Użyj,
Runnable
jeśli nie robi ani nie może rzucać.źródło
public static void wrapCall(Runnable r) { r.run(); }
. DziękiThe lambda:
faktycznie reprezentuje implementację interfejsu takiego jak:
który jest zupełnie inny niż ten, który zdefiniowałeś. Dlatego pojawia się błąd.
Ponieważ nie możesz przedłużyć
@FunctionalInterface
ani wprowadzić nowego, myślę, że nie masz wielu opcji.Optional<T>
Interfejsów można jednak użyć do wskazania, że brakuje niektórych wartości (typu zwracanego parametru lub parametru metody). Nie uprości to jednak ciała lambda.źródło
Something
funkcja nie może być podtypem mojegoAction
typu i nie mogę mieć dwóch różnych typów.Możesz utworzyć pod-interfejs dla tego specjalnego przypadku:
Używa domyślnej metody, aby zastąpić odziedziczoną sparametryzowaną metodę
Void execute(Void)
, delegując wywołanie do prostszej metodyvoid execute()
.W rezultacie korzystanie z niego jest znacznie prostsze:
źródło
Action<T, U>
zadeklarowano w pytaniu .....Myślę, że ta tabela jest krótka i przydatna:
Jak powiedziano na inne odpowiedzi, odpowiednią opcją dla tego problemu jest
Runnable
źródło
Nie jest możliwe. Funkcja, która ma typ zwrotny nieważny (nawet jeśli jest
Void
), musi zwrócić wartość. Można jednak dodać doAction
tego metody statyczne, które pozwalają „utworzyć”Action
:To pozwoli ci napisać:
źródło
Dodaj metodę statyczną do interfejsu funkcjonalnego
Wynik
źródło
Nie sądzę, aby było to możliwe, ponieważ definicje funkcji nie pasują do twojego przykładu.
Twoje wyrażenie lambda jest oceniane dokładnie tak jak
podczas gdy twoja deklaracja wygląda
jako przykład, jeśli masz następujący interfejs
jedyny rodzaj funkcji (podczas tworzenia instancji), który będzie kompatybilny
a brak instrukcji return lub argumentu spowoduje błąd kompilatora.
Dlatego jeśli zadeklarujesz funkcję, która pobiera argument i zwraca jedną, myślę, że nie jest możliwe przekonwertowanie go na funkcję, która nie jest wymieniona powyżej.
źródło
Tylko dla odniesienia, który interfejs funkcjonalny może być użyty do odwołania do metody w przypadkach, gdy metoda rzuca i / lub zwraca wartość.
źródło