Java Academy · Lektion

Egna funktionella gränssnitt

Definiera ett eget med @FunctionalInterface.

Lektion 4 av 413 steg

Egna funktionella gränssnitt är en gratis lektion i Java Academy på CoddyKit. Detta är lektion 4 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Java Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Java Academy innehåller totalt 4 lektioner.

Vad som gör ett gränssnitt funktionellt

Ett funktionellt gränssnitt har exakt en abstrakt metod (SAM). Det är den enda metoden som en lambda implementerar.

  • Default- och statiska metoder räknas inte mot gränsen.
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"));
    }
}

Annoteringen @FunctionalInterface

@FunctionalInterface instruerar kompilatorn att upprätthålla regeln om en enda abstrakt metod. Om du av misstag lägger till en andra abstrakt metod misslyckas kompileringen.

@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));
    }
}

Varför annoteringen är användbar

Annoteringen dokumenterar avsikten och skyddar kontraktet. Utan den fungerar gränssnittet fortfarande som ett funktionellt gränssnitt, men en kollega kan bryta det genom att lägga till ytterligare en abstrakt metod.

@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"));
    }
}

Anpassat gränssnitt med generics

Ditt gränssnitt kan vara generiskt, precis som de inbyggda gränssnitten.

@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);
    }
}

Default-metoder är tillåtna

Ett funktionellt gränssnitt får ha default-metoder. De lägger till funktionalitet utan att bryta regeln om en enda abstrakt metod.

@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));
    }
}

Statiska metoder är också tillåtna

Statiska metoder kan fungera som fabriksmetoder, på samma sätt som 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));
    }
}

Kasta kontrollerade undantag

Om din abstrakta metod deklarerar ett kontrollerat undantag får lambdan kasta det. Det inbyggda Function-gränssnittet kan inte göra detta, vilket är en anledning att definiera ett eget.

@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"));
    }
}

Skicka anpassade gränssnitt till metoder

Ditt gränssnitt blir en parametertyp, vilket gör att anropare kan tillhandahålla beteende via lambdor.

@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));
    }
}

Gränssnitt med tre argument

JDK tillhandahåller endast gränssnitt med ett eller två argument. För tre eller fler argument behöver du definiera ett eget.

@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));
    }
}

Metodreferenser passar anpassade gränssnitt

Alla metoder vars signatur matchar SAM kan tillhandahållas som en metodreferens.

@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("   "));
    }
}

Anonym klass jämfört med lambda

En lambda är en kortfattad ersättning för en anonym klass som implementerar ett funktionellt gränssnitt. Båda ger samma beteende.

@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();
    }
}

Snabbkontroll

Vad garanterar @FunctionalInterface?

Sammanfattning

Du definierade egna funktionella gränssnitt:

  • Ett funktionellt gränssnitt har exakt en abstrakt metod (SAM).
  • @FunctionalInterface upprätthåller regeln vid kompilering.
  • Default- och statiska metoder, generics och kontrollerade undantag är alla tillåtna.
  • Anpassade gränssnitt täcker sådant som JDK inte tillhandahåller, till exempel funktioner med tre argument eller lambdor som kastar kontrollerade undantag.
Gratis att börja

Lär dig Java med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
104
Lektioner
374

Vanliga frågor

Är lektionen ”Egna funktionella gränssnitt” gratis?

Ja – hela texten till ”Egna funktionella gränssnitt” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Java Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i Java Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Egna funktionella gränssnitt”?

Definiera ett eget med @FunctionalInterface. Ni övar på Java Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Java Academy?

Du behöver inga förkunskaper. Utbildningen i Java Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Egna funktionella gränssnitt”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Java Academy-lektionen?

Ja. Varje Java Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Function och BiFunction
  2. Supplier och Consumer
  3. Predicate och komposition
  4. Egna funktionella gränssnitt
← Tillbaka till Java Academy