JDK1.8 函式式介面 Consumer & Supplier 以及 JAVA新紀元 λ表示式的到來
背景什麼的被吞了,直接進入主題
函式式介面(定義自己百度,一大堆)
因為看了一些關於JDK1.8函式式介面的文章,發現基本上都是糊里糊塗一筆帶過.所以就抽空趕緊整理了一下.
還是附上幾個學習瞭解的傳送門 :
Consumer 函式式介面
JDK 原始碼
/**
* 接受單個輸入引數並且不返回結果的操作。
* 與大多數其他功能介面不同, Consumer預期通過副作用進行操作。
*
* @since 1.8
*/
@FunctionalInterface
public interface Consumer<T> {
/**
* 對給定的引數執行此操作。
*
* @param t the input argument
*/
void accept(T t);
/**
* 返回一個組合的Consumer ,依次執行此操作,然後執行after操作。
* 如果執行任一操作會丟擲異常,它將被轉發到組合操作的呼叫者。
* 如果執行此操作會引發異常,則不會執行after操作。
*
* @param 此操作後執行的操作
* @return 一個組成的 Consumer ,依次執行 after操作
* @throws NullPointerException - if after is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
複製程式碼
剛拿過來看的時候可能會有一些繞,但是我們換個角度來看一下.
Consumer 直譯過來就是消費者的意思,那我們是不是可以理解成消費程式碼.既然他要消費,那我們就要給他提供程式碼.
來看一個簡單的demo
public void testConsumer1() {
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s + "?");
}
};
consumer.accept("李磊");
}
複製程式碼
輸出結果
李磊?
複製程式碼
簡單解釋一下
Consumer
是一個介面,所以當我們直接使用的話,要實現其 accept()
方法,而這個方法的引數,就是我們定義介面時候給到的泛型,這裡給的是一個String
型別,方法當中的內容,就是我們所謂的消費程式碼,當呼叫accept()
方法時執行.
注意 : 也就是上面提到的通過副作用處理,我不清楚這個單詞翻譯的是否準確,看了很多博主和一些機器翻譯都是這個意思,但我個人的理解意思,更趨近於說是通過側面來解決問題.
再看一下 consumer.accept("李磊")
這一句,這裡便是真正的執行的地方,也就是呼叫的我們剛剛自行實現的accept()
方法.
讓我們繼續剛剛的demo往下看
這種寫法和上面在JDK1.8環境中是等價的. 主要就是利用到了1.8中的 λ 表示式.
public void testConsumer1() {
Consumer<String> consumer = s -> System.out.println(s + "?");
consumer.accept("李磊");
}
複製程式碼
下面的例子均使用λ表示式完成
泛型為自定義物件時
public void testConsumerToSupplier() {
Consumer<Person> consumer = person -> {
person.setName("張穎");
person.setSize(34);
};
Person person = new Person();
consumer.accept(person);
System.out.println("person = " + person);
}
複製程式碼
輸入結果:
person = Person{name='張穎', size=34}
複製程式碼
泛型為自定義介面時
public interface People {
void come(Person person);
}
複製程式碼
public void testConsumerAndInterfaceFunction() {
Consumer<People> consumer = people -> {
people.come(new Person("李四", 23));
people.come(new Person("找錢", 34));
people.come(new Person("孫儷", 45));
};
consumer.accept(this::print);
}
public void print(Person person) {
System.out.println("person = " + person);
}
複製程式碼
輸出結果
person = Person{name='李四', size=23}
person = Person{name='找錢', size=34}
person = Person{name='孫儷', size=45}
複製程式碼
如果到了這裡還沒有明白怎麼回事,我建議你親自動手敲上那麼一遍.真的,如果還不懂來杭州,我當面給你講.
Supplier 函式式介面
還是一樣,先看一下JDK原始碼
/**
* 獲得物件的一個函式式介面
*
* @since 1.8
*/
@FunctionalInterface
public interface Supplier<T> {
/**
* 得到一個物件
*
* @return 目標物件
*/
T get();
}
複製程式碼
這個是不是看起來很容易理解了,Supplier
的意思是供應商,那我們是不是可以把他理解成一個商場,然後你告訴他你想要的東西是什麼樣子的,它是不是就會給你了.
來看一下這個簡單的demo
void testSupplier1() {
Supplier<String> supplier = () -> "這是你要的字串";
String str = supplier.get();
System.out.println("str = " + str);
}
複製程式碼
執行結果:
str = 這是你要的字串
複製程式碼
繼續自定義物件
void testSupplier2() {
Supplier<Person> supplier = () -> {
Person person = new Person();
person.setName("張三");
person.setSize(32);
return person;
};
Person person = supplier.get();
System.out.println("person = " + person);
}
複製程式碼
執行結果
person = Person{name='張三', size=32}
複製程式碼
再來刺激的自定義介面
void testSupplier3() {
Supplier<People> supplier = new Supplier<People>() {
@Override
public People get() {
People people = new People() {
@Override
public void come(Person person) {
System.out.println("person = " + person)
}
};
return people;
}
};
People people = supplier.get();
people.come(new Person("李四", 24));
}
複製程式碼
輸出結果
person = Person{name='李四', size=24}
複製程式碼
看好別眨眼,λ表示式的寫法 下面的一行和上面的一堆是等價的
void testSupplier4() {
Supplier<People> supplier = () -> person -> System.out.println("person = " + person);
People people = supplier.get();
people.come(new Person("李四", 24));
}
複製程式碼
輸出結果
person = Person{name='李四', size=24}
複製程式碼
想必看到這你不光明白了 Supplier
的用法,更清楚的λ表示式的用處了.
寫在最後,寫這篇文章的原因是因為在整理工廠模式的時候遇到的一些問題
工廠模式簡單的是不能再簡單了,但是隨著技術的發展,也出現了一些新穎的工廠方法.CTS
便是其中之一.
至於Consumer
&Supplier
應用在工廠模式的程式碼如下,因為比較特殊,寫在了一起,想要親自體檢覆制貼上執行TTT
類的main()
方法即可
/**
* @author lvgo
* @version 1.0
* @Description: CTS實現工廠模式
* @date 18-8-24 下午3:57
*/
public interface CTS {
static CTS getCts(Consumer<Peoples> consumer) {
Map<String, Supplier<Persons>> map = new HashMap<>();
consumer.accept(map::put);
return person -> map.get(person).get();
}
Persons getPerson(String name);
}
interface Peoples {
void come(String name, Supplier<Persons> personSupplier);
}
class TTT {
public static void main(String[] args) {
CTS cts = CTS.getCts(people -> {
people.come("張三", () -> new Persons("張三"));
people.come("李四", () -> new Persons("李四"));
people.come("王五", () -> new Persons("王五"));
});
Persons person = cts.getPerson("王五");
System.out.println("persons = " + person);
}
}
class Persons {
private String name;
public Persons() {
}
public Persons(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + "'}'";
}
}
複製程式碼
CTS工廠模式說明: Consumer To Supplier 自造詞,無處可尋,他處偶遇純屬抄襲;
通過Peoples
介面的come()
方法,可以動態在CTS工廠內新增person
,然後使其具於生產該例項的能力.
參考文獻