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

方法引用使用方式小结:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/nrsc272420199/article/details/84718802