Własne interfejsy funkcyjne
Definiowanie własnego interfejsu za pomocą @FunctionalInterface
Własne interfejsy funkcyjne to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.
Co sprawia, że interfejs jest funkcyjny
Interfejs funkcyjny ma dokładnie jedną metodę abstrakcyjną (SAM). To właśnie tę pojedynczą metodę implementuje lambda.
- Metody domyślne i statyczne nie są uwzględniane w tym limicie.
interface Greeter {
String greet(String name);
}
public class Main {
public static void main(String[] args) {
Greeter g = name -> "Hello, " + name;
System.out.println(g.greet("Ada"));
}
}Adnotacja @FunctionalInterface
@FunctionalInterface nakazuje kompilatorowi egzekwować regułę jednej metody abstrakcyjnej. Jeśli przypadkowo zostanie dodana druga metoda abstrakcyjna, kompilacja zakończy się niepowodzeniem.
@FunctionalInterface
interface Calculator {
int compute(int a, int b);
}
public class Main {
public static void main(String[] args) {
Calculator add = (a, b) -> a + b;
System.out.println(add.compute(3, 4));
}
}Dlaczego adnotacja jest pomocna
Adnotacja dokumentuje zamiar i chroni kontrakt. Bez niej interfejs nadal działa jako funkcyjny, ale inny programista mógłby go zepsuć, dodając kolejną metodę abstrakcyjną.
@FunctionalInterface
interface Transformer {
String apply(String input);
}
public class Main {
public static void main(String[] args) {
Transformer reverse = s -> new StringBuilder(s).reverse().toString();
System.out.println(reverse.apply("abc"));
}
}Własny interfejs z typami generycznymi
Interfejs może być generyczny, podobnie jak interfejsy wbudowane.
@FunctionalInterface
interface Converter<S, T> {
T convert(S source);
}
public class Main {
public static void main(String[] args) {
Converter<String, Integer> toInt = Integer::parseInt;
System.out.println(toInt.convert("123") + 1);
}
}Metody domyślne są dozwolone
Interfejs funkcyjny może zawierać metody default. Dodają one zachowanie bez naruszania reguły jednej metody abstrakcyjnej.
@FunctionalInterface
interface Operation {
int apply(int x);
default Operation then(Operation next) {
return x -> next.apply(this.apply(x));
}
}
public class Main {
public static void main(String[] args) {
Operation inc = x -> x + 1;
Operation dbl = x -> x * 2;
System.out.println(inc.then(dbl).apply(5));
}
}Metody statyczne również są dozwolone
Metody statyczne mogą pełnić funkcję fabryk, podobnie jak Function.identity().
@FunctionalInterface
interface Mapper {
int map(int x);
static Mapper identity() {
return x -> x;
}
}
public class Main {
public static void main(String[] args) {
System.out.println(Mapper.identity().map(99));
}
}Zgłaszanie wyjątków kontrolowanych
Jeśli metoda abstrakcyjna deklaruje wyjątek kontrolowany, lambda może go zgłaszać. Wbudowany Function nie pozwala na to, co stanowi jeden z powodów definiowania własnego interfejsu.
@FunctionalInterface
interface RiskyParser {
int parse(String s) throws NumberFormatException;
}
public class Main {
public static void main(String[] args) {
RiskyParser p = Integer::parseInt;
System.out.println(p.parse("77"));
}
}Przekazywanie własnych interfejsów do metod
Interfejs staje się typem parametru, dzięki czemu wywołujący mogą dostarczać zachowanie za pomocą lambd.
@FunctionalInterface
interface IntCombiner {
int combine(int a, int b);
}
public class Main {
static int reduce(int[] arr, IntCombiner c) {
int acc = arr[0];
for (int i = 1; i < arr.length; i++) acc = c.combine(acc, arr[i]);
return acc;
}
public static void main(String[] args) {
int[] data = {1, 2, 3, 4};
System.out.println(reduce(data, (a, b) -> a + b));
}
}Interfejs przyjmujący trzy argumenty
JDK udostępnia interfejsy przyjmujące tylko jeden lub dwa argumenty. W przypadku trzech lub większej liczby argumentów należy zdefiniować własny interfejs.
@FunctionalInterface
interface TriFunction<A, B, C, R> {
R apply(A a, B b, C c);
}
public class Main {
public static void main(String[] args) {
TriFunction<Integer, Integer, Integer, Integer> sum3 = (a, b, c) -> a + b + c;
System.out.println(sum3.apply(1, 2, 3));
}
}Referencje do metod pasują do własnych interfejsów
Każda metoda, której sygnatura odpowiada SAM, może zostać przekazana jako referencja do metody.
@FunctionalInterface
interface StringTest {
boolean check(String s);
}
public class Main {
public static void main(String[] args) {
StringTest blank = String::isBlank;
System.out.println(blank.check(" "));
}
}Klasa anonimowa a lambda
Lambda jest zwięzłym zamiennikiem klasy anonimowej implementującej interfejs funkcyjny. Oba rozwiązania zapewniają takie samo zachowanie.
@FunctionalInterface
interface Action {
void run();
}
public class Main {
public static void main(String[] args) {
Action old = new Action() {
public void run() { System.out.println("anonymous"); }
};
Action neo = () -> System.out.println("lambda");
old.run();
neo.run();
}
}Szybkie sprawdzenie
Co gwarantuje @FunctionalInterface?
Podsumowanie
Zdefiniowano własne interfejsy funkcyjne:
- Interfejs funkcyjny ma dokładnie jedną metodę abstrakcyjną (SAM).
@FunctionalInterfaceegzekwuje tę regułę podczas kompilacji.- Metody domyślne i statyczne, typy generyczne oraz wyjątki kontrolowane są dozwolone.
- Własne interfejsy uzupełniają luki, których nie pokrywa JDK, na przykład obsługują funkcje z trzema argumentami lub lambdy zgłaszające wyjątki kontrolowane.
Często zadawane pytania
Czy lekcja „Własne interfejsy funkcyjne” jest bezpłatna?
Tak — pełny tekst „Własne interfejsy funkcyjne” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Własne interfejsy funkcyjne”?
Definiowanie własnego interfejsu za pomocą @FunctionalInterface Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Java Academy?
Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Własne interfejsy funkcyjne”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?
Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Function i BiFunction
- Supplier i Consumer
- Predicate i kompozycja
- Własne interfejsy funkcyjne