lambda表示式之方法引用----java
阿新 • • 發佈:2018-12-03
1.概念 ---- 什麼是方法引用???
對於每一個java類來說,它們都主要有三種方法,即普通方法、靜態方法和構造方法。而方法引用就是利用函式式介面+lambda表示式(這裡的lambda表示式並非前面提到的帶"->“符號的表示式,而是使用雙冒號”::"的一種lambda表示式)的方式對類中的方法進行引用,之所以稱為“引用”,是因為這種方式不像以往我們對類中的方法進行操作時,就是直接呼叫該方法,或者說執行該方法,這中方式會根據指定的函式式介面建立一個該介面的一個例項,方法的真正執行需要通過該例項去觸發執行。
2. 程式碼說話
看完概念部分的介紹,可能很多人還是會有云裡霧裡的感覺,下面用幾個小栗子來具體的說一下:
2.1 入門----靜態方法的方法引用
package com.nrsc.lambda.MethodReference;
import java.util.function.Consumer;
//Cat類
class Cat {
private String name = "加菲貓";
/**
* 靜態方法
*/
public static void eat(Cat cat) {
System.out.println(cat + "喜歡吃魚");
}
@Override
public String toString () {
return this.name;
}
}
public class Demo {
public static void main(String[] args) {
//靜態方法的方法引用
/**
* 通過分析可以得知靜態方法eat需要輸入的引數為Cat例項,無返回結果,
* 那麼它與JDK所提供的函式式介面Consumer<T>所需要的輸入和輸出是一致的,
* 因此該靜態方法可以使用函式式介面Consumer<T> + 雙冒號lambda表示式 的方式進行引用
* 引用方式如下:
*/
Cat cat = new Cat();
Consumer<Cat> eatMethod = Cat::eat;//靜態方法的雙冒號表示式是類名::方法名
eatMethod.accept(cat);
}
}
從上面的入門栗子裡可以看出,其實方法引用很簡單,只需要分析清楚方法的輸入引數型別和引數格式,以及返回結果型別,然後由此選擇合適的函式式介面,再配合雙冒號("::")lambda表示式,就可以完成方法引用了。
2.2 靜態方法+非靜態方法+建構函式的方法引用示例:
方法引用其實並不難,這裡弄了一段程式碼,對各種方法引用都進行了一下測試:
package lambda;
import java.util.function.*;
//Dog類
class Dog {
private String name = "哮天犬";
/**
* 預設10斤狗糧
*/
private int food = 10;
public Dog() {
}
/**
* 帶引數的建構函式
*
* @param name
*/
public Dog(String name) {
this.name = name;
}
/**
* 狗叫,靜態方法
*
* @param dog
*/
public static void bark(Dog dog) {
System.out.println(dog + "叫了");
}
/**
* 吃狗糧 JDK
*
* 預設會把當前例項傳入到非靜態方法,引數名為this,位置是第一個;
*
* @param num
* @return 還剩下多少斤
*/
public int eat(int num) {
System.out.println("吃了" + num + "斤狗糧");
this.food -= num;
return this.food;
}
// 和上面的eat方法效果一模一樣
// public int eat(Dog this, int num) {
// System.out.println("吃了" + num + "斤狗糧");
// this.food -= num;
// return this.food;
// }
@Override
public String toString() {
return this.name;
}
}
public class MethodRefrenceDemo {
public static void main(String[] args) {
Dog dog = new Dog();
// 靜態方法的方法引用
Consumer<Dog> consumer2 = Dog::bark;
consumer2.accept(dog); // 哮天犬叫了
System.out.println("===================================");
// 非靜態方法,使用物件例項的方法引用
// Function<Integer, Integer> function = dog::eat;
// 由於方法的輸入引數型別和輸出引數型別相同,所以可以使用一元函式介面
// UnaryOperator<Integer> function = dog::eat;
// 當然也可以使用帶型別的一元函式介面
IntUnaryOperator function = dog::eat;
System.out.println("剩下" + function.applyAsInt(2) + "斤"); // 吃了2斤狗糧 剩下8斤
System.out.println("++++++++++++++++++++++++++++++++++++");
/**
* 大家應該知道,在非靜態方法裡,可以使用this關鍵字, 它的原理其實就是在形參裡預設將當前物件傳給了方法,引數名就是this
*
* 因此非靜態方法eat還可以看成是一個有兩個輸入一個輸出的函式BiFunction<T ,U ,R> 此時可以使用(類名::方法名)的方式進行方法引用
* 栗子如下:
*/
BiFunction<Dog, Integer, Integer> eatFunction = Dog::eat;
System.out.println("還剩下" + eatFunction.apply(dog, 2) + "斤");
System.out.println("******************************************");
// 建構函式的方法引用
Supplier<Dog> supplier = Dog::new;
System.out.println("建立了新物件:" + supplier.get());
// 帶引數的建構函式的方法引用
Function<String, Dog> function2 = Dog::new;
System.out.println("建立了新物件:" + function2.apply("旺財"));
}
}