Java - 函數式介面

你好,未來的Java開發者!今天,我們將進入Java中函數式介面的精彩世界。如果你是編程新手,不必擔心;我會一步一步引導你了解這個概念,就像我過去幾年教學中對無數學生所做的那樣。所以,來一杯咖啡(或你最喜歡的飲料),我們一起深入探討吧!

Java - Functional Interfaces

函數式介面是什麼?

想像一下,你在一個派對上,被分配的角色是DJ。你的工作很簡單:播放音樂。你不需要擔心提供食物或裝飾場地。在Java中,函數式介面就像那個DJ——它有一個特定的任務要完成,而且做得很好。

在技術術語中,函數式介面是一個包含正好一個抽象方法的介面。它可以有其他方法,但這些方法必須是默認或靜态方法。單一的抽象方法賦予了函數式介面其“函數式”的本質。

示例1:一個簡單的函數式介面

@FunctionalInterface
interface Greeter {
void greet(String name);
}

在這個示例中,Greeter是一個函數式介面。它只有一個抽象方法greet,該方法接受一個String參數並不返回任何東西(void)。

@FunctionalInterface注解

你可能已經注意到我們示例中的@FunctionalInterface注解。這就像在我們的介面上貼上“DJ”徽章。它告訴Java,“嘿,這個介面應該是函數式的!”如果我們不小心添加了另一個抽象方法,Java會給我們一個錯誤,幫助我們保持介面的函數式本質。

使用函數式介面

現在我們知道了函數式介面是什麼,我們來看看如何使用它們。函數式介面的一個最酷的地方是我们可以用它們與lambda表達式一起使用,這些表達式就像是编写方法的簡略方式。

示例2:將函數式介面與Lambda表達式一起使用

public class GreeterTest {
public static void main(String[] args) {
Greeter friendlyGreeter = (name) -> System.out.println("你好," + name + "! 你怎麼樣?");
friendlyGreeter.greet("Alice");

Greeter formalGreeter = (name) -> System.out.println("下午好," + name + "。希望你一切安好。");
formalGreeter.greet("史密斯先生");
}
}

在這個示例中,我們使用Greeter介面創建了兩個不同的歡迎者。lambda表達式(name) -> ...即時實現了greet方法。這就像為兩個不同的派對雇傭兩個不同的DJ一樣!

當你運行這段代碼時,你會看到:

你好,Alice! 你怎麼樣?
下午好,史密斯先生。希望你一切安好。

Java中的函數式介面類型

Java提供了許多內置的函數式介面,使我們的生活更加輕鬆。讓我們看看一些最常使用的:

1. Predicate

Predicate<T>介面用於一個參數的布爾值函數。它就像一個可以回答是或不是的問題。

import java.util.function.Predicate;

public class PredicateExample {
public static void main(String[] args) {
Predicate<Integer> isAdult = age -> age >= 18;

System.out.println("20是成年年齡嗎? " + isAdult.test(20));
System.out.println("15是成年年齡嗎? " + isAdult.test(15));
}
}

這將輸出:

20是成年年齡嗎? true
15是成年年齡嗎? false

2. Function<T,R>

Function<T,R>介面表示一個接受一個參數並生成結果的函數。它就像一臺將某物投入並產生其他東西的機器。

import java.util.function.Function;

public class FunctionExample {
public static void main(String[] args) {
Function<String, Integer> stringLength = str -> str.length();

System.out.println("'Hello'的長度: " + stringLength.apply("Hello"));
System.out.println("'Java is awesome'的長度: " + stringLength.apply("Java is awesome"));
}
}

這將輸出:

'Hello'的長度: 5
'Java is awesome'的長度: 16

3. Consumer

Consumer<T>介面表示一個接受單個輸入參數並返回無結果的操作。它就像一個黑洞,消耗數據但不產生任何東西。

import java.util.function.Consumer;

public class ConsumerExample {
public static void main(String[] args) {
Consumer<String> printer = message -> System.out.println("列印: " + message);

printer.accept("你好,函數式介面!");
printer.accept("Java很有趣!");
}
}

這將輸出:

列印: 你好,函數式介面!
列印: Java很有趣!

4. Supplier

Supplier<T>介面表示結果的供應商。它不接受參數但產生一個值。它就像一臺不需要你放入東西就能給你一些東西的售貨機。

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

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

System.out.println("隨機數字: " + randomNumberSupplier.get());
System.out.println("另一個隨機數字: " + randomNumberSupplier.get());
}
}

這將輸出兩個0到99之間的隨機數字,例如:

隨機數字: 42
另一個隨機數字: 73

Java 8之前存在的函數式介面

在Java 8引入函數式介面概念之前,Java有一些符合定義的介面。這些主要用於事件處理和並發編程。讓我們看看一些示例:

1. Runnable

Runnable介面自Java早期時代以來就存在。它通常用於創建線程。

public class RunnableExample {
public static void main(String[] args) {
Runnable helloRunnable = () -> System.out.println("來自線程的問候!");
new Thread(helloRunnable).start();
}
}

這將輸出:

來自線程的問候!

2. Comparator

Comparator介面用於定義對象的自定義排序。

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

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

Comparator<String> lengthComparator = (s1, s2) -> s1.length() - s2.length();

Arrays.sort(names, lengthComparator);

System.out.println("按長度排序: " + Arrays.toString(names));
}
}

這將輸出:

按長度排序: [Bob, Alice, David, Charlie]

結論

恭喜你!你剛剛走出了Java中函數式介面的第一步。我們已經介绍了它們是什麼、如何使用它們,並查看了一些常見類型。請記住,函數式介面就像你Java工具箱中的專用工具。它們幫助你编写更乾淨、表達性更强的代碼。

隨著你繼續Java之旅,你會發現函數式介面的用處越來越多。當涉及到流和集合時,它們尤其強大,這將在我們未來的課程中進行講解。

繼續練習,保持好奇心,最重要的是,編程愉快!Java是一門廣闊且激動人心的語言,你已經在掌握它的道路上邁出了堅實的一步。直到下次,編程愉快!

Credits: Image by storyset