Writing in the front

We already know that lambda expressions are anonymous functions that can be used to implement a functional interface.

It is natural to think that class methods are functions, essentially the same as lambda expressions. Can we also use class methods to implement a functional interface? The answer is yes. We call this method reference.

Sample code for this article is available from Gitee: gitee.com/cnmemset/ja…

Obtain all column, can pay attention to the public number [member said]

Method references

A typical example is writing a word and its length to a Map:

public static void simpleMethodReference(a) {
    Map wordMap = new HashMap<>();

    // Same as wordMap.computeIfAbsent("hello", s -> s.length());
    wordMap.computeIfAbsent("hello", String::length);

    // Output is {hello=5}
    System.out.println(wordMap);
}
Copy the code

In the above code, String:: Length is the method reference, which separates the class name or object from the method name with ::, the class name or object to the left, and the method name to the right.

In general, there are four cases for method references:

  1. Object ::instanceMethod — object + instanceMethod
  2. Class::staticMethod — Class name + staticMethod
  3. Class::instanceMethod — Class name + instanceMethod
  4. Class::new — Class name + keyword new, also known as constructor reference

1. object::instanceMethod

Object ::instanceMethod, :: is an object on the left, and :: is the instanceMethod name on the right.

It is equivalent to a lambda expression that provides the argument list of an instanceMethod method.

For example for the String STR (String STR = “”) :

STR ::compareTo equivalent to s -> str.compareTo(s)

Example code is as follows:

public static void objectInstanceMethodReference(a) {
    String me = "me";

    // The key of wordMap is the given word, and the value is case-insensitive, compared to the word "me"
    Map wordMap = new HashMap<>();

    // me::compareToIgnoreCase is equivalent to s -> me.com
    wordMap.computeIfAbsent("him", me::compareToIgnoreCase);
    wordMap.computeIfAbsent("you", s ->  me.compareToIgnoreCase(s));

    System.out.println(wordMap);
}
Copy the code

The output of the above code is:

{him=5, you=-12}
Copy the code

2. Class::staticMethod

Class::staticMethod, :: on the left is a Class, and on the right is the staticMethod name.

This is equivalent to a lambda expression that provides the argument list of a staticMethod method.

Such as:

System.out::println is equivalent to x -> system.out.print (x)

Sample code:

public static void classStaticMethodReference(a) {
    List list = Arrays.asList("Guangdong"."Zhejiang"."Jiangsu");

    // system.out ::println is equivalent to s -> system.out.println (s)
    list.forEach(System.out::println);
}
Copy the code

The output of the above code is:

Guangdong
Zhejiang
Jiangsu
Copy the code

3. Class::instanceMethod

For Class::instanceMethod, :: is a Class to the left and :: is the instanceMethod name to the right.

If the argument list for instanceMethod is (x, y), then Class::instanceMethod is equivalent to the lambda expression (obj, x, y) -> obj.instancemethod (x, y), Where obj is an object instance of Class.

Such as:

String::length is equivalent to s -> s.length()

String: : compareToIgnoreCase equivalent to (s1, s2) – > s1.com pareToIgnoreCase (s2)

Sample code:

public static void classInstanceMethodReference(a) {
    Map wordMap = new HashMap<>();
    Integer wordLen = wordMap.computeIfAbsent("hello", String::length);

    System.out.println(wordMap);
}
Copy the code

The output of the above code is:

{hello=5}
Copy the code

4. Class::new

For Class::new, new refers to the constructor of the Class, so it is also called a constructor reference.

Class::new may be equivalent to x -> new Class(x, y) or (x, y) -> new Class(x, y). The compiler will infer this from the context at compile time.

Such as:

BigDecimal::new, depending on the context, may be equivalent to (String s) -> new BigDecimal(s)

In particular, array types can also be referenced using constructors. An array type has only one construction argument that represents the length of the array:

String[]::new is equivalent to x -> new String[x]

Sample code:

public static void ctorMethodReference(a) {
    List list = Arrays.asList("1.1"."2.2"."3.3");

    // BigDecimal::new Is equivalent to s -> new BigDecimal(s)
    Stream stream = list.stream().map(BigDecimal::new);

    List decimalList = stream.collect(Collectors.toList());

    System.out.println(decimalList);

    // Build a new Stream. The previous Stream has been closed
    Stream stream1 = list.stream().map(BigDecimal::new);

    // BigDecimal[]::new, array constructor reference, equivalent to x -> new BigDecimal[x]
    BigDecimal[] decimalArray = stream1.toArray(BigDecimal[]::new);

    for(BigDecimal d : decimalArray) { System.out.println(d); }}Copy the code

The output of the above code is:

[1.1, 2.2, 3.3]
1.1
2.2
3.3
Copy the code

5. This: : instanceMethod and super: : instanceMethod

For this::instanceMethod, it is easy to understand, as if the this keyword were an instance object of the current class.

Such as:

This ::equals = x -> this.equals(x)

For super::instanceMethod, it’s a little more complicated, equivalent to calling the parent version of the specified method on this.

Sample code:

public class SuperMethodReferenceExample {
    public static void main(String[] args) {
        ThreadWaiter waiter = new ThreadWaiter();
        waiter.run();
    }

    public static class Waiter {
        public void sayHi(a) {
            System.out.println("Hello, man!"); }}public static class ThreadWaiter extends Waiter {
        @Override
        public void sayHi(a) {
            System.out.println("Hello, thread!");
        }

        public void run(a) {
            // Specifies that the sayHi method of the parent class Waiter is called
            Thread t = new Thread(super::sayHi); t.start(); }}}Copy the code

The output of the above code is:

Hello, man!
Copy the code

conclusion

A method reference can be viewed as a syntactic sugar for a lambda expression.