转载

一起来学Java8(三)——方法引用

在一起来学Java8(一)——函数式编程中有一个简单的函数式编程的例子:

 1import java.util.function.Consumer;
 2
 3class Person {
 4    public static void sayHello(String name) {
 5        System.out.println("hello " + name);
 6    }
 7}
 8
 9public class TestPerson {
10
11    public static void main(String[] args) {
12        work(Person::sayHello); // hello Jim
13    }
14
15    public static void work(Consumer<String> consumer) {
16        consumer.accept("Jim");
17    }
18}
复制代码

其中Person::sayHello被称为方法引用,方法引用可以用Lambda表达式来代替,代码如下:

1public static void main(String[] args) {
2    work((name) -> {
3        System.out.println("hello " + name);
4    }); // hello Jim
5}
复制代码

方法引用和Lambda关系

方法引用和Lambda表达式之间有什么关系呢?

方法引用可以看做是Lambda表达式的一种快捷方式。这种快捷方式是建立在某种条件之上的,大致可以分为三类:

  1. 静态方法引用
  2. 自身类型方法引用
  3. 现有实例方法引用

静态方法引用

上面提到的例子就是静态方法引用,我们还可以使用其它静态方法来替代

1public static void main(String[] args) {
2    work(String::toString);
3    work(String::toLowerCase);
4}
复制代码

可以看到,Lambda表达式有一个参数(String name),String.toString和String.toLowerCase和Person.sayHello也是同样的参数类型, 只要是参数签名一致都可以替换使用。

自身类型方法引用

当Lambda表达式的方法体内直接使用参数中的对象方法,可以使用这种方式。比如下面这个例子:

 1public static void main(String[] args) {
 2    // 方式1,使用Lambda表达式
 3    print("hello", (String s) -> s.toLowerCase());
 4    // 方式2,使用方法引用
 5    print("hello", String::toLowerCase);
 6}
 7
 8private static void print(String argu, Consumer<String> consumer) {
 9    consumer.accept(argu);
10}
复制代码

Lambada表达式中有个参数(String s) 在方法体中直接使用了参数对象中的方法 s.toLowerCase(),因此可以简写为:String::toLowerCase

在来一个复杂点的例子:

 1package learn.java8.ch3;
 2
 3import java.util.function.Function;
 4
 5class Goods {
 6    private int price;
 7
 8    public int getPrice() {
 9        return price;
10    }
11
12    public void setPrice(int price) {
13        this.price = price;
14    }
15}
16
17class GoodsService {
18    private Goods goods;
19
20    public GoodsService(Goods goods) {
21        super();
22        this.goods = goods;
23    }
24
25    public void showPrice(Function<Goods, Integer> fun) {
26        int price = fun.apply(goods);
27        System.out.println("商品价格:" + price);
28    }
29}
30
31public class TestPerson2 {
32
33    public static void main(String[] args) {
34        Goods goodsApple = new Goods();
35        goodsApple.setPrice(100);
36
37        GoodsService service = new GoodsService(goodsApple);
38        // 方式1,使用Lambda表达式
39        service.showPrice((Goods goods) -> {
40            return goods.getPrice();
41        });
42
43        // 方式2,使用方法引用
44        service.showPrice(Goods::getPrice);
45    }
46
47}
复制代码

方式1中有个Lambda表达式,参数为Goods goods,在方法体中又直接调用了goods对象的getPrice,因此可以简化为:service.showPrice(Goods::getPrice);

现有实例方法引用

当Lambda表达式的方法体内没有使用参数中的对象方法,使用了其它对象的方法。比如下面这个例子

 1package learn.java8.ch3;
 2
 3import java.util.function.Consumer;
 4
 5class Dog {
 6    private int age;
 7
 8    public Dog(int age) {
 9        super();
10        this.age = age;
11    }
12
13    public void say(String name) {
14        System.out.println("dog age is " + age + ", dog name is " + name);
15    }
16}
17
18public class TestPerson4 {
19
20    public static void main(String[] args) {
21        Dog dog = new Dog(3);
22        // 方式1,使用Lambda表达式
23        print("Tom", (String s) -> dog.say(s));
24        // 方式2,实例对象方法引用
25        print("Tom", dog::say);
26    }
27
28    private static void print(String argu, Consumer<String> consumer) {
29        consumer.accept(argu);
30    }
31
32}
复制代码

第二种跟第三种的区别就是,Lambda方法体中有没有直接使用Lambda参数中的方法。

下面总结一下Lambda表达式和方法引用的等价关系:

  • (Dog dog) -> dog.getAge() 等价于 Dog::getAge

  • () -> XXClass.run() 等价于 XXClass::run

  • (dog, name) -> dog.say(name) 等价于 Dog::say

  • (name) -> dog.say(name) 等价于 dog::say

原文  https://juejin.im/post/5e7f3a7e6fb9a03c3c3505cf
正文到此结束
Loading...