1. 程式人生 > >lambda表示式之方法引用----java

lambda表示式之方法引用----java

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("旺財"));
	}
}

方法引用使用方式小結:

在這裡插入圖片描述