New in JDK8 – method references
What is a method reference?
In fact, I’ve written about this in previous articles, but I just wrote about it, and I didn’t elaborate on it. Now let’s look at an example
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class FunctionRefTest1 {
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
list.add(new Student("Zhang".20));
list.add(new Student("Bill".19));
list.add(new Student("Fifty".23));
list.add(new Student("Liu six".22));
// Sort the list using the Comparator
// short form of lambda
// list.sort((o1,o2)-> o1.getAge()-o2.getAge());
// lambda is the simplest form of lambda
list.sort( Comparator.comparingInt(Student::getAge));
for (Student student : list) {
System.out.println(student.getName()+""+student.getAge()); }}}Copy the code
Sort ((o1,o2)-> o1.getage () -o2.getage ()); list.sort((o1, O2)-> o1.getage ()); And list. Sort (Comparator.com paringInt Student: : getAge ()); Both codes have the same effect, while list.sort(Comparator.comparingInt(Student::getAge)); So this is using a method reference, what’s the effect? Method references make lambda expressions less redundant, thus simplifying the way lambda expressions are written.
Preliminary experience
- Method references can be understood to eliminate the redundancy of lambda expressions and simplify writing.
- Format:
AA::BB
What is AA, what is BB, depends on the situation, and I’ll elaborate on that. Okay
Maybe you are still foggy, ok, come again an example, let you digest once
public class FunctionRefTest2 {
public static void main(String[] args) {
getSum((a)->{
int ans = 0;
for (int i : a) {
ans += i;
}
System.out.println("sum = "+ans);
});
}
public static void getSum(Consumer<int[]> consumer){
int[] a = {1.2.3.4.5.6.7.8.9}; consumer.accept(a); }}Copy the code
Here we’re going to implement array summation, which is fine for us to do, but we’ll see that there’s a lot of stuff in lambda{}, and if there’s a method out there that can also implement array summation, like this
public class FunctionRefTest2 {
public static void main(String[] args) {
getSum((a)->{
int ans = 0;
for (int i : a) {
ans += i;
}
System.out.println("sum = "+ans);
});
}
public static void sum(int[] a){
int ans = 0;
for (int i : a) {
ans += i;
}
System.out.println("sum = "+ans);
}
public static void getSum(Consumer<int[]> consumer){
int[] a = {1.2.3.4.5.6.7.8.9}; consumer.accept(a); }}Copy the code
The outer sum method repeats the code inside the {} of the lambda expression, resulting in a redundant lambda expression, in which case the method reference comes into play
public class FunctionRefTest2 {
public static void main(String[] args) {
getSum(FunctionRefTest2::sum);
}
public static void sum(int[] a){
int ans = 0;
for (int i : a) {
ans += i;
}
System.out.println("sum = "+ans);
}
public static void getSum(Consumer<int[]> consumer){
int[] a = {1.2.3.4.5.6.7.8.9}; consumer.accept(a); }}Copy the code
So, lambda expressions are a little bit cleaner, a little bit higher? Now that you know something about method references, let’s take a look at the rest of it
The way a method is referenced
- Object name :: Method name
- Class name :: Static method name
- Class name :: References instance methods
- Class name :: constructor
- Array :: constructor
Precautions for method references:
- The parameters of the referenced method must be the same as those of the abstract method in the interface
- When an interface abstract method has a return value, the referenced method must also have a return value
- Method references can only refer to existing methods
How can we do this without examples? Let’s take a look at a couple of examples, just to get to the bottom of it
Object name :: Method name
This is the most common usage. If a member method already exists in a class, it can be referenced by object name
package com.features.functionReference;
import java.util.Date;
import java.util.function.Supplier;
public class FunctionRefTest3 {
public static void main(String[] args) {
Date now = new Date();
Supplier<Long> s1 = () -> now.getTime();
System.out.println("Current time obtained without using method references:"+s1.get());
Supplier<Long> s2 = now::getTime;
System.out.println("Current time obtained using method reference:"+s2.get()); }}Copy the code
Now is an object of type Date
Class name :: Static method name
One of the common forms
package com.features.functionReference;
import java.util.function.Supplier;
// Class name :: static method name
public class FunctionRefTest4 {
public static void main(String[] args) {
Supplier<Long> s1 = ()-> System.currentTimeMillis();
System.out.println("Current time obtained without using method references:"+s1.get());
Supplier<Long> s2 = System::currentTimeMillis;
System.out.println("Current time obtained without using method references:"+s2.get()); }}Copy the code
System is a class
Class name :: References instance methods
In Java object-oriented, class names can only call static methods, and class names refer to instance methods with the premise that they actually take the first argument as the caller of the method
package com.features.functionReference;
import java.util.function.BiFunction;
import java.util.function.Function;
// Class name :: references instance methods
public class FunctionRefTest5 {
public static void main(String[] args) {
Function<String,Integer> f1 = s -> s.length();
System.out.println("The length of hello from unused method references is:"+f1.apply("hello"));
Function<String,Integer> f2 = String::length;
System.out.println("The length of hello obtained using method references is:"+f2.apply("hello"));
BiFunction<String,Integer,String> f3 = String::substring;
System.out.println("The length of hello obtained using method references is:"+f3.apply("hello".2)); }}Copy the code
S is an instance of String, and length is an instance method of S
Class name :: constructor
Because the constructor name is exactly the same as the class name, constructor references are used in the format :: new,
package com.features.functionReference;
import com.features.lambda.demo02.Student;
import java.util.function.BiFunction;
import java.util.function.Supplier;
// Class name :: constructor
public class FunctionRefTest6 {
public static void main(String[] args) {
Supplier<Student> s1 = () -> new Student();
System.out.println("Result before method reference is used:"+s1.get());
Supplier<Student> s2 = Student::new;
System.out.println("Result after using method reference:"+s2.get());
BiFunction<String,Integer,Student> function = Student::new;
System.out.println("Result after using method reference:"+function.apply("Zhang".20)); }}Copy the code
Student is a concrete class
Array :: constructor
package com.features.functionReference;
import java.util.function.Function;
// Array :: constructor
public class FunctionRefTest7 {
public static void main(String[] args) {
Function<Integer,String[]> f1 = len->new String[len];
System.out.println("Length of array obtained before method reference is used:"+f1.apply(5).length);
Function<Integer,String[]> f2 = String[]::new;
System.out.println("Length of array after using method reference:"+f2.apply(5).length); }}Copy the code