Learn java 8 together -- method reference

Keywords: Programming Lambda Java

Let's learn java 8 (1) - there is a simple example of functional programming in functional programming:

import java.util.function.Consumer;

class Person {
    public static void sayHello(String name) {
        System.out.println("hello " + name);
    }
}

public class TestPerson {

	public static void main(String[] args) {
		work(Person::sayHello); // hello Jim
	}
	
	public static void work(Consumer<String> consumer) {
		consumer.accept("Jim");
	}
}

Where Person::sayHello is called method reference, which can be replaced by Lambda expression. The code is as follows:

public static void main(String[] args) {
	work((name) -> {
		System.out.println("hello " + name);
	}); // hello Jim
}

Method references and Lambda relationships

What is the relationship between method references and Lambda expressions?

Method references can be seen as a shortcut to Lambda expressions. This shortcut is based on certain conditions and can be roughly divided into three categories:

  1. Static method reference
  2. Self type method reference
  3. Existing instance method references

Static method reference

The above example is a static method reference. We can use other static methods instead.

public static void main(String[] args) {
	work(String::toString);
	work(String::toLowerCase);
}

As you can see, a Lambda expression has a parameter (String name). String.toString, String.toLowerCase and Person.sayHello are the same parameter types. As long as the parameter signature is consistent, they can be replaced.

Self type method reference

This can be used when the method body of a Lambda expression directly uses the object method in the parameter. For example:

public static void main(String[] args) {
	// Mode 1, using Lambda expressions
	print("hello", (String s) -> s.toLowerCase());
	// Method 2, use method reference
	print("hello", String::toLowerCase);
}

private static void print(String argu, Consumer<String> consumer) {
	consumer.accept(argu);
}

There is a parameter (String s) in the lambda expression that directly uses the method s.toLowerCase() in the parameter object in the method body, so it can be abbreviated as: String::toLowerCase

In an example of a complex point:

package learn.java8.ch3;

import java.util.function.Function;

class Goods {
	private int price;

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}
}

class GoodsService {
	private Goods goods;

	public GoodsService(Goods goods) {
		super();
		this.goods = goods;
	}

	public void showPrice(Function<Goods, Integer> fun) {
		int price = fun.apply(goods);
		System.out.println("Commodity price:" + price);
	}
}

public class TestPerson2 {

	public static void main(String[] args) {
		Goods goodsApple = new Goods();
		goodsApple.setPrice(100);

		GoodsService service = new GoodsService(goodsApple);
		// Mode 1, using Lambda expressions
		service.showPrice((Goods goods) -> {
			return goods.getPrice();
		});
		
		// Method 2, use method reference
		service.showPrice(Goods::getPrice);
	}

}

There is a Lambda expression in method 1. The parameter is Goods goods, and the getPrice of goods object is called directly in the method body. Therefore, it can be simplified as: service.showPrice(Goods::getPrice).

Existing instance method references

When the object method in the parameter is not used in the method body of Lambda expression, other object methods are used. Here's an example

package learn.java8.ch3;

import java.util.function.Consumer;

class Dog {
	private int age;

	public Dog(int age) {
		super();
		this.age = age;
	}

	public void say(String name) {
		System.out.println("dog age is " + age + ", dog name is " + name);
	}
}

public class TestPerson4 {

	public static void main(String[] args) {
		Dog dog = new Dog(3);
		// Mode 1, using Lambda expressions
		print("Tom", (String s) -> dog.say(s));
		// Mode 2, instance object method reference
		print("Tom", dog::say);
	}

	private static void print(String argu, Consumer<String> consumer) {
		consumer.accept(argu);
	}

}

The second one is different from the third one in that whether the method in the Lambda method body directly uses the method in the Lambda parameter.

Here is a summary of the equivalence between Lambda expressions and method references:

  • (dog dog) - > dog. Getage() is equivalent to Dog::getAge
  • () - > xxclass. Run() is equivalent to XXClass::run
  • (dog, name) - > dog.say (name) is equivalent to Dog::say
  • (name) - > dog.say (name) is equivalent to dog::say

Summary

This article mainly introduces method references, and demonstrates three different method references.

Regularly share technology dry goods, learn together and make progress together!

Posted by blakey on Mon, 21 Oct 2019 22:04:30 -0700