Java - Funktionale Schnittstellen

Hallo, zukünftige Java-Entwickler! Heute erleben wir eine aufregende Reise in die Welt der funktionalen Schnittstellen in Java. Keine Sorge, wenn du neu bei der Programmierung bist; ich werde dich Schritt für Schritt durch dieses Konzept führen, genau wie ich es für unzählige Studenten in meinen Jahren des Unterrichtens getan habe. Also, nimm dir einen Tasse Kaffee (oder dein Lieblingsgetränk) und lasst uns einsteigen!

Java - Functional Interfaces

Was sind funktionale Schnittstellen?

Stell dir vor, du bist auf einer Party und hast die Rolle des DJs. Deine Aufgabe ist einfach: Musik abzuspielen. Du musst dich nicht um das Servieren von Essen oder die Dekoration des Veranstaltungsortes kümmern. In Java ist eine funktionale Schnittstelle wie dieser DJ - sie hat eine spezifische Aufgabe, die sie gut erfüllt.

In technischer Sprache ist eine funktionale Schnittstelle eine Schnittstelle, die genau eine abstrakte Methode enthält. Sie kann andere Methoden haben, aber diese müssen Default- oder statische Methoden sein. Die einzelne abstrakte Methode ist es, die der funktionalen Schnittstelle ihre "funktionale" Natur verleiht.

Beispiel 1: Eine einfache funktionale Schnittstelle

@FunctionalInterface
interface Begrüßler {
void begrüßen(String name);
}

In diesem Beispiel ist Begrüßler eine funktionale Schnittstelle. Sie enthält nur eine abstrakte Methode begrüßen, die einen String-Parameter nimmt und nichts zurückgibt (void).

@FunctionalInterface Annotation

Du hast vielleicht die @FunctionalInterface-Annotation in unserem Beispiel bemerkt. Das ist wie ein "DJ"-Abzeichen für unsere Schnittstelle zu setzen. Es teilt Java mit: "Hey, diese Schnittstelle ist dazu gedacht, funktional zu sein!" Wenn wir versehentlich eine weitere abstrakte Methode hinzufügen, gibt uns Java einen Fehler,帮助我们 beizubehalten die funktionale Natur unserer Schnittstelle.

Verwendung von funktionalen Schnittstellen

Nun, da wir wissen, was funktionale Schnittstellen sind, schauen wir uns an, wie wir sie verwenden können. Eine der coolsten Dinge bei funktionalen Schnittstellen ist, dass wir sie mit Lambda-Ausdrücken verwenden können, die wie Kurzschreibweisen für Methoden funktionieren.

Beispiel 2: Verwendung einer funktionalen Schnittstelle mit Lambda-Ausdruck

public class BegrüßlerTest {
public static void main(String[] args) {
Begrüßler freundlicherBegrüßler = (name) -> System.out.println("Hallo, " + name + "! Wie geht es dir?");
freundlicherBegrüßler.begrüßen("Alice");

Begrüßler formalierterBegrüßler = (name) -> System.out.println("Guten Tag, " + name + ". Ich hoffe, es geht dir gut.");
formalierterBegrüßler.begrüßen("Herr Smith");
}
}

In diesem Beispiel erstellen wir zwei verschiedene Begrüßler mit unserer Begrüßler-Schnittstelle. Die Lambda-Ausdrücke (name) -> ... implementieren die begrüßen-Methode sofort. Es ist wie zwei verschiedene DJs für zwei verschiedene Partys zu engagieren!

Wenn du diesen Code ausführst, wirst du sehen:

Hallo, Alice! Wie geht es dir?
Guten Tag, Herr Smith. Ich hoffe, es geht dir gut.

Typen funktionaler Schnittstellen in Java

Java bietet mehrere eingebaute funktionale Schnittstellen, um unser Leben einfacher zu machen. Schauen wir uns einige der am häufigsten verwendeten an:

1. Predicate

Die Predicate<T>-Schnittstelle wird für boolsche Funktionen mit einem Argument verwendet. Sie ist wie eine Frage, die mit ja oder nein beantwortet werden kann.

import java.util.function.Predicate;

public class PredicateBeispiel {
public static void main(String[] args) {
Predicate<Integer> istErwachsen = alter -> alter >= 18;

System.out.println("Ist 20 ein Erwachsenenalter? " + istErwachsen.test(20));
System.out.println("Ist 15 ein Erwachsenenalter? " + istErwachsen.test(15));
}
}

Dies wird ausgeben:

Ist 20 ein Erwachsenenalter? true
Ist 15 ein Erwachsenenalter? false

2. Function<T,R>

Die Function<T,R>-Schnittstelle represents a function that accepts one argument and produces a result. Sie ist wie eine Maschine, die etwas nimmt und etwas anderes zurückgibt.

import java.util.function.Function;

public class FunctionBeispiel {
public static void main(String[] args) {
Function<String, Integer> stringLänge = str -> str.length();

System.out.println("Länge von 'Hallo': " + stringLänge.apply("Hallo"));
System.out.println("Länge von 'Java ist großartig': " + stringLänge.apply("Java ist großartig"));
}
}

Dies wird ausgeben:

Länge von 'Hallo': 5
Länge von 'Java ist großartig': 16

3. Consumer

Die Consumer<T>-Schnittstelle represents an operation that accepts a single input argument and returns no result. Sie ist wie ein schwarzes Loch, das Daten konsumiert, aber nichts produziert.

import java.util.function.Consumer;

public class ConsumerBeispiel {
public static void main(String[] args) {
Consumer<String> drucker = nachricht -> System.out.println("Drucken: " + nachricht);

drucker.accept("Hallo, funktionale Schnittstelle!");
drucker.accept("Java ist Spass!");
}
}

Dies wird ausgeben:

Drucken: Hallo, funktionale Schnittstelle!
Drucken: Java ist Spass!

4. Supplier

Die Supplier<T>-Schnittstelle represents a supplier of results. Sie nimmt keine Argumente, aber produziert einen Wert. Sie ist wie ein Automat, der dir etwas gibt, ohne dass du etwas hineinlegst.

import java.util.function.Supplier;
import java.util.Random;

public class SupplierBeispiel {
public static void main(String[] args) {
Supplier<Integer> zufallsZahlSupplier = () -> new Random().nextInt(100);

System.out.println("Zufällige Zahl: " + zufallsZahlSupplier.get());
System.out.println("Noch eine zufällige Zahl: " + zufallsZahlSupplier.get());
}
}

Dies wird zwei zufällige Zahlen zwischen 0 und 99 ausgeben, zum Beispiel:

Zufällige Zahl: 42
Noch eine zufällige Zahl: 73

Vorhandene funktionale Schnittstellen vor Java 8

Bevor Java 8 das Konzept der funktionalen Schnittstellen einführte, hatte Java einige Schnittstellen, die der Definition entsprachen. Diese wurden hauptsächlich für Ereignisverarbeitung und konkurrierende Programmierung verwendet. Schauen wir uns einige Beispiele an:

1. Runnable

Die Runnable-Schnittstelle gibt es seit den Anfängen von Java. Sie wird häufig für das Erstellen von Threads verwendet.

public class RunnableBeispiel {
public static void main(String[] args) {
Runnable halloRunnable = () -> System.out.println("Hallo von einem Thread!");
new Thread(halloRunnable).start();
}
}

Dies wird ausgeben:

Hallo von einem Thread!

2. Comparator

Die Comparator-Schnittstelle wird verwendet, um benutzerdefinierte Ordnungen für Objekte zu definieren.

import java.util.Arrays;
import java.util.Comparator;

public class ComparatorBeispiel {
public static void main(String[] args) {
String[] namen = {"Alice", "Bob", "Charlie", "David"};

Comparator<String> längeComparator = (s1, s2) -> s1.length() - s2.length();

Arrays.sort(namen, längeComparator);

System.out.println("Sortiert nach Länge: " + Arrays.toString(namen));
}
}

Dies wird ausgeben:

Sortiert nach Länge: [Bob, Alice, David, Charlie]

Schlussfolgerung

Herzlichen Glückwunsch! Du hast gerade deine ersten Schritte in die Welt der funktionalen Schnittstellen in Java gemacht. Wir haben behandelt, was sie sind, wie man sie verwendet und haben einige gängige Typen betrachtet. Denke daran, dass funktionale Schnittstellen wie spezialisierte Werkzeuge in deinem Java-Werkzeugkasten sind. Sie helfen dir, sauberer und ausdrucksstärkeren Code zu schreiben.

Während du deinen Java-Weg fortsetzt, wirst du immer mehr Verwendungen für funktionale Schnittstellen finden. Sie sind besonders mächtig, wenn es um Streams und Sammlungen geht, das werden wir in zukünftigen Lektionen behandeln.

Weiter üben, neugierig bleiben und vor allem Spaß beim Coden haben! Java ist eine große und aufregende Sprache, und du bist gut auf dem Weg, sie zu meistern. Bis zum nächsten Mal, fröhliches Coden!

Credits: Image by storyset