在這篇文章中,咱們將瞭解到在Java8下如何進行函數式編程。java
所謂的函數式編程就是把函數名字當作值進行傳遞,而後接收方拿到這個函數名進行調用。編程
首先來看下JavaScript如何進行函數調用ide
var Person = { sayHello: function(name) { alert('hello ' + name); } }; function work(fn) { fn('Jim'); } work(Person.sayHello); // hello Jim
在這個例子中,sayHello
函數被當作一個參數傳遞到另外一個work
函數當中,而後work調用給定的函數。函數式編程
在Java中,充當函數的角色是類中方法,在本篇文章當中提到的函數泛指方法。函數
接下來看下Java8中一個簡單的函數式編程例子:設計
import java.util.function.Consumer; class Person { public static void sayHello(String name) { System.out.println("hello " + name); } } public class TestPerson { public static void main(String[] args) { work(Person::sayHello); // hello Jim } public static void work(Consumer<String> consumer) { consumer.accept("Jim"); } }
從這個例子中能夠看到,Java8傳遞函數的方式跟JavaScript不同,在Java8當中傳遞函數的方式是:方法引用::方法名稱
,如:String.valueOf,String.toString。接收參數Consumer能夠先不用去了解,後面會講到。code
爲了接收傳遞過來的函數引用,Java設計者提出了一個函數式接口
的概念接口
函數式接口定義:一個接口裏面只有一個抽象方法
。ip
以下面幾個接口都是函數式接口:源碼
查看Runnable類的源碼能夠發現,在類上方定義了一個@FunctionalInterface
註解
@FunctionalInterface public interface Runnable { public abstract void run(); }
當作一個標記使用,標記當前接口是一個函數式接口,若是你的接口有多個抽象方法或沒有抽象方法,那麼會編譯報錯。它的做用有點相似於@override
註解,有輔助做用,但不是必須的。若是你想設計一個函數式接口,那麼最好把它加上。
// 編譯不經過,必需要有一個抽象方法 @FunctionalInterface public interface InterfaceA { } // 編譯經過,只有一個抽象方法 @FunctionalInterface public interface InterfaceB { void run(); } // 編譯不經過,只能有一個抽象方法 @FunctionalInterface public interface InterfaceC { void run(); void run2(); } // 編譯經過,run2是默認方法,並非抽象方法 // 在這裏只有一個run抽象方法 @FunctionalInterface public interface InterfaceD { void run(); default void run2() {}; }
在例子InterfaceD中涉及到了接口默認方法default void run2() {};
,這裏略過不講,後續文章中會有提到。
咱們能夠實現一個自定義的函數式接口,替代Consumer
// 自定義函數式接口 @FunctionalInterface public interface FunctionCaller<T> { void call(T t); } public class TestPerson2 { public static void main(String[] args) { work(Person::sayHello); } public static void work(FunctionCaller<String> caller) { caller.call("Jim"); } }
本篇主要講解了在Java8下如何進行函數式編程 ,以及如何定義和使用一個函數式接口。