簡單理解Java的functional interface

閱讀時間約 6 分鐘
在學Java的人也許多少人會跟小的一樣不是很理解functional interface到底在幹嘛,也覺得語法很多此一舉。希望能夠在此拋磚引玉。

先講結論

重點說在前面。我的理解是,functional interface是為了讓Java像是Python或R等其他語言一樣,可以把一個方法直接分離出來向物件或者參數使用,而不是只能呼叫。請聽小的娓娓道來。

再講原因: 簡單來說是Java對於OOP的堅持的副作用

因為Java是個非常堅持物件導向(Object-oriented programming)的語言,所以語法不會像Javascript, R或Python一樣可以直接定義函數於global environment中:
R的語法:
hello <- function(x) { print('hello')} 然後hello()就可以呼叫
Python的語法:
def hello():
  print("hello")
一樣直接用hello()就可以呼叫
注意到在R跟Python中 hello()都不必掛在某個特定的class中,這點Java等非常強調物件導向的語言就做不到,所以Java提出了functional interface的方案。

先複習一下什麼是interface跟functional interface

interface(介面)一開始被設計出來的功能是為了定規格。在開發程式的時候為了保證某些物件的方法名稱在同一個團隊中的不同開發者能夠維持一致,所以大家會先討論好某些規格,再定義抽象方法出來。抽象方法就是只有名稱,裡面沒有程式碼,而且強迫所有使用該interface的class必須寫出來的方法,否則編譯器就不給過(雖然新版的Java允許Interface裡面定義非抽象方法,例如private跟static methods)。這麼一來團隊就可以把使用同一個interface的方法分給不同人員去開發。
例如某團隊在開發某個網頁程式可以允許使用者利用Google, Facebook, Line帳號來登入,那麼假設這三個不同的登入方式分別是不同的class,也由不同的開發者來撰寫程式碼,那麼如果定義一個interface,叫IAuthenticate裡面有個抽象方法auth(),那麼前端負責開發登入頁面的人員就不需要知道這三個class分別到底怎麼寫,只要知道反正可以呼叫auth()方法就對了。
functional interface的定義是「只有一個抽象方法的interface」。乍看之下這個定義真的很廢,也很令人費解,感覺好像是在限縮interface的能力,從能夠定義很多方法到只能定義一個。

functional interface的用意其實跟interface不一樣

functional interface就是要解決Java沒有辦法簡單地像其他語言一樣把方法當物件傳給其他物件使用或者到時候再決定要不要執行的問題。以前述hello()的例子來說,如果按照Java物件導向的邏輯本來應該寫在某個class裡面:
class HelloPrinter() {
  public void hello() {
    System.out.println("hello!");
  }
}
使用的時候主程式裡面要這樣寫
new HelloPrinter().hello();
整個感覺很多此一舉
所以functional interface就出現了,若我們只管hello()這個方法吃進去什麼跟吐出來什麼(什麼都不吃,也沒有回傳什麼),那麼我們可以定義一個廣用的functional interface,名稱不重要,反正就這個functional interface的方法不接收參數,也不回傳東西,那麼
interface IVoider() {
  void nameDoesntMatter();
}
這個時候就直接傳lambda 方法就好
IVoider hello = () -> {System.out.println("hello");}
訂完IVoider這個functional interface之後,這個所有不吃參數並且不回傳物件的方法是都可以這樣寫存取程物件了,此處hello變成了一個到時候可以當參數傳進別的class的物件了。跟前述的R或Python寫法是否有異曲同工之妙呢?
重點是因為訂了IVoider這個functional interface,所以可以做出一堆所有不吃參數並且不回傳物件的方法是都可以這樣寫存取程物件
IVoider hey = () -> {System.out.println("hey");}
IVoider helloWorld= () -> {System.out.println("helloWorld");}
由此可見,對於functional interface而言,反正使用的時候是直接去指定lambda方法,或method reference(在其他文章中將解釋),所以方法名稱根本沒差,也因此不像interface是用來規範的。

一些Java已經幫你定義好的functional interface

既然functional interface的重點是要像其他語言那樣把方法變成可以傳進別的class的物件,而且方法名稱不重要,只有吃什麼跟吐什麼重要,那麼可以見得當然會有一些已經定義好的functinoal interfaces可以使用。
1. Predicate<T>: 吃 一個任意類型物件當參數,吐出boolean
可以想見常常在需要過濾某些東西的filter中使用。
Predicate<String> sFilter = (s) <- s.startsWith("S");
sFilter變成了一個可以快速檢查字串是不是S開頭的過濾器
2. Consumer<T>: 吃一個任意物件當參數,不吐東西(void)
3. Supplier<T>: 不吃參數,吐出一個任意物件類型T
4. UnaryOperator<T>吃一個物件,吐出一個相同的物件
5. BiFunction<T, T, U>吃兩個類型相同物件,再吐出一個不一定相同類型的物件,會用在Map裡面用來有條件地更新Collection元素中。(待其他文章詳細說明)
以上。

即將進入廣告,捲動後可繼續閱讀
為什麼會看到廣告
    avatar-img
    10會員
    15內容數
    對工程師友善的(目前免費)英文教材 #工程師 #Coding #Python #Django #English #英文 #文法 #語言學習 #程式
    留言0
    查看全部
    avatar-img
    發表第一個留言支持創作者!
    你可能也想看
    Google News 追蹤
    Thumbnail
    本章節是Java入門的第八天,主要介紹物件導向的概念。這包括了類別、建構子、存取修飾子、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、Lambda表達式、泛型和反射等主題。每個主題都配有相關的程式碼範例,以協助讀者更好地理解這些概念。
    Thumbnail
    本章節主要介紹Java語言中的函數(也稱為方法)的使用,包括函數的基本結構、函數表達式(Lambda表達式)、箭頭函數、匿名函數的使用,以及如何呼叫函數、如何使用函數參數和函數的返回值等內容。通過學習本章節,讀者將能夠熟練掌握Java語言中的函數相關知識,並能夠在實際編程中靈活運用。
    Thumbnail
    此章節旨在介紹Java的基本語法、註解和變數的使用。透過學習,讀者將了解Java程式的基本結構、程式進入點的定義、如何撰寫單行和多行註解,以及如何宣告和初始化變數。
    Thumbnail
    這篇文章的目的是對Java程式設計語言進行介紹,包括它的特性、應用範疇、主要使用者,以及相關的學習資源和常見的庫與框架。此外,它也提供了一些學習Java的渠道,以及與Java相關的其他知識。
    ※ TypeScript範例說明: interface ITest { test1: string test2: number print: (arg: string[]) => boolean } class Test implements ITest { public te
    Thumbnail
    這一節談的是用物件導向程式設計(object-oriented programming, OOP)的方式來實作隨機漫步。
    Thumbnail
    本文介紹了Python中的物件導向程式設計的重要概念,包括類別、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型和反射。每個概念都有對應的程式碼範例來說明其用法和功能。這些概念對於理解和使用Python進行物件導向程式設計至關重要。
    Thumbnail
    default methods 似乎也引起不小的討論,因為 default methods 加上可以實作多個介面,已經有點像 C++ 的多重繼承了,只差在沒辦法繼承成員變數而已,是好是壞就看怎麼使用了。我個人覺得還蠻方便的
    Thumbnail
    lambda 函式,又稱為“匿名函式”,是一種在 Python 中快速定義單行函式的方法,與 def 定義函式不同,lambda 函式不需要命名。本文將介紹 lambda函式的基礎語法,以及實際應用範例演示。
    Thumbnail
    本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。
    Thumbnail
    本章節是Java入門的第八天,主要介紹物件導向的概念。這包括了類別、建構子、存取修飾子、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、Lambda表達式、泛型和反射等主題。每個主題都配有相關的程式碼範例,以協助讀者更好地理解這些概念。
    Thumbnail
    本章節主要介紹Java語言中的函數(也稱為方法)的使用,包括函數的基本結構、函數表達式(Lambda表達式)、箭頭函數、匿名函數的使用,以及如何呼叫函數、如何使用函數參數和函數的返回值等內容。通過學習本章節,讀者將能夠熟練掌握Java語言中的函數相關知識,並能夠在實際編程中靈活運用。
    Thumbnail
    此章節旨在介紹Java的基本語法、註解和變數的使用。透過學習,讀者將了解Java程式的基本結構、程式進入點的定義、如何撰寫單行和多行註解,以及如何宣告和初始化變數。
    Thumbnail
    這篇文章的目的是對Java程式設計語言進行介紹,包括它的特性、應用範疇、主要使用者,以及相關的學習資源和常見的庫與框架。此外,它也提供了一些學習Java的渠道,以及與Java相關的其他知識。
    ※ TypeScript範例說明: interface ITest { test1: string test2: number print: (arg: string[]) => boolean } class Test implements ITest { public te
    Thumbnail
    這一節談的是用物件導向程式設計(object-oriented programming, OOP)的方式來實作隨機漫步。
    Thumbnail
    本文介紹了Python中的物件導向程式設計的重要概念,包括類別、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型和反射。每個概念都有對應的程式碼範例來說明其用法和功能。這些概念對於理解和使用Python進行物件導向程式設計至關重要。
    Thumbnail
    default methods 似乎也引起不小的討論,因為 default methods 加上可以實作多個介面,已經有點像 C++ 的多重繼承了,只差在沒辦法繼承成員變數而已,是好是壞就看怎麼使用了。我個人覺得還蠻方便的
    Thumbnail
    lambda 函式,又稱為“匿名函式”,是一種在 Python 中快速定義單行函式的方法,與 def 定義函式不同,lambda 函式不需要命名。本文將介紹 lambda函式的基礎語法,以及實際應用範例演示。
    Thumbnail
    本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。