在 JDK8 提供函數(shù)式接口,這樣 java 這門語(yǔ)言也成為同時(shí)支持命令式編程夕凝、面向?qū)ο缶幊桃约昂瘮?shù)式編程的多范式的開(kāi)發(fā)語(yǔ)言。今天通過(guò)示例代碼給大家分享一下我們?nèi)绾卧趯?shí)際開(kāi)發(fā)中應(yīng)用 JDK8 提供函數(shù)式接口來(lái)重構(gòu)我們的代碼芥映。
interface ITransFormat{
String format(String input);
}
class MTrans{
private final String input;
public MTrans(String input) {
this.input = input;
}
public void trans(ITransFormat iTransFormat){
System.out.println(iTransFormat.format(input) + " is transformed to weichat format");
}
}
public class FPDemoA {
public static void main(String[] args) {
MTrans trans = new MTrans("jianshu");
trans.trans( input -> "content of " + input );
}
上面代碼大家可能再熟悉不過(guò)溅话,也沒(méi)有什么新意。這個(gè)的public void trans(ITransFormat iTransFormat)
接收一個(gè)接口作為參數(shù)盅称。這個(gè)接口稍微有些不同肩祥,這里我給大家描述一下他不同之處,就是只有一個(gè)要實(shí)現(xiàn)的方法缩膝,這方法有一個(gè)輸入String input
和一個(gè)輸出String
混狠。那么顯然這是一個(gè)函數(shù)式接口。
所以我們無(wú)需定義ITransFormat
接口定義參數(shù)的類型疾层,直接就是一個(gè)函數(shù)式Function<String,String>
來(lái)定義參數(shù)的類型将饺。如下
class MTrans{
private final String input;
public MTrans(String input) {
this.input = input;
}
public void trans(Function<String,String> iTransFormat){
System.out.println(iTransFormat.apply(input) + " is transformed to weichat format");
}
}
這樣我們就可以少聲明一個(gè)接口來(lái)定義參數(shù)類型,好處不僅這些痛黎,這種函數(shù)式接口類型還支持 andThen
來(lái)進(jìn)行擴(kuò)展予弧。
public static void main(String[] args) {
MTrans trans = new MTrans("jianshu");
Function<String,String> handler = input -> "content of " + input;
trans.trans( handler.andThen( body -> " written by zidea" + body) );
}
JDK8 給我們提供許多函數(shù)式接口的類型
方法引用
Consumer<T> 就是一種消費(fèi)型函數(shù)式接口,因?yàn)橹挥休斎霙](méi)有輸出舅逸,我們定義函數(shù)如果只有輸入就可以表示為這種方法引用
Consumer<String> consumer = s -> System.out.println(s);
Consumer<String> consumer = System.out::println;
將函數(shù)賦值個(gè)一個(gè) consumer 的引用桌肴,讓后可以通過(guò) accept 進(jìn)行調(diào)用。
Consumer<String> consumer = System.out::println;
consumer.accept("recieve input");
靜態(tài)方法的方法引用
class Animal{
private String name = "aAnimal";
/**
* 靜態(tài)方法
* @param animal
*/
public static void walk(Animal animal){
System.out.println(animal + " is walking");
}
@Override
public String toString() {
return this.name;
}
}
上面是靜態(tài)方法的方法引用琉历,通過(guò)::將類的靜態(tài)方法賦值給函數(shù)式接口類型的引用
Consumer<Animal> animalConsumer = Animal::walk;
Animal animal = new Animal();
animalConsumer.accept(animal);
非靜態(tài)方法坠七,使用對(duì)象實(shí)例來(lái)方法引用
public int eat(int num){
System.out.println("can eat " + num + " kg");
this.food -= num;
return this.food;
}
下面是非靜態(tài)方法的方法引用,值得注意的是引用輸入類型和輸出類型都是 int 類型我們可以簡(jiǎn)化為UnaryOperator<Integer>
表示接口
Consumer<Animal> animalConsumer = Animal::walk;
Animal animal = new Animal();
animalConsumer.accept(animal);
UnaryOperator<Integer> function = animal::eat;
System.out.println(" " + function.apply(2) + "kg");
因?yàn)橐呀?jīng)確定類型為 Int 所以可以直接使用IntUnaryOperator
這樣從而省略泛型的判斷旗笔。
IntUnaryOperator function = animal::eat;
System.out.println(" " + function.applyAsInt(2) + "kg");
非靜態(tài)方法彪置,使用的對(duì)象實(shí)例的方法引用,實(shí)際上在方法 eat 中有一個(gè)隱式參數(shù)就是 Animal ,實(shí)例化時(shí)候調(diào)用構(gòu)造函數(shù)創(chuàng)建一個(gè) Animal 的實(shí)例作為名為 this 傳入非靜態(tài)方法蝇恶。
Animal animal = new Animal();
animal.eat(1);
public int eat(Animal this,int num){
System.out.println("can eat " + num + " kg");
this.food -= num;
return this.food;
}
JDK 默認(rèn)會(huì)把當(dāng)前實(shí)例傳入到非靜態(tài)方法拳魁,參數(shù)名為 this,位置是第一個(gè)
使用類名來(lái)引用方法
BiFunction<Animal,Integer,Integer> eatFunc = Animal::eat;
System.out.println(eatFunc.apply(animal,2));
構(gòu)造函數(shù)方法引用
Supplier<Animal> supplier = Animal::new;
System.out.println("create a new " +supplier.get());
帶參數(shù)的構(gòu)造函數(shù)的方法引用
public Animal(String name){
this.name = name;
}
Function<String,Animal> function1 = Animal::new;
function1.apply("duck");