方法引用
从JDK1.8开始,可以使用方法引用。
我们用Lambda表达式来实现匿名方法。但有些情况下,我们用Lambda表达式仅仅是调用一些已经存在的方法,除了调用动作外,没有其他任何多余的动作,在这种情况下,我们倾向于通过方法名来调用它,而Lambda表达式可以帮助我们实现这一要求,它使得Lambda在调用那些已经拥有方法名的方法的代码更简洁、更容易理解。方法引用可以理解为Lambda表达式的另外一种表现形式。
如果lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用
常见形式:
类型 | 语法 | 对应的Lambda表达式 |
---|---|---|
静态方法引用 | 类名::staticMethod | (args) -> 类名.staticMethod(args) |
实例方法引用 | inst::instMethod | (args) -> inst.instMethod(args) |
对象方法引用 | 类名::instMethod | (inst,args) -> inst.instMethod(args) |
构建方法引用 | 类名::new | (args) -> new 类名(args) |
1、静态方法引用举例
package com.hong.method;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;
import java.util.UUID;
/**
* @Author hongCheng
* @Date 2021/4/25 17:46
* @Version 1.0
*/
public class StaticTest {
public static void main(String[] args) {
Person[] people = new Person[10];
for (int i = 0; i < 10; i++) {
//random即随机数发生器,使用值卡需要使用Randomize语句进行随机数种子的初始化
// random产生的是伪随机数或者说是用一种复杂的方法计算得到的序列值,
// 因此每次运算时需要一个不同的种子值。种子值不同,得到的序列值也不同。因此也就是真正的随机数。
// VB里用new Random()来表示。
people[i] = new Person(new Random().nextInt(100), UUID.randomUUID().toString().substring(0, 3));
}
//Arrays数组的工具类 Collections是集合的工具类
System.out.println(Arrays.asList(people));
//排序
Arrays.sort(people,new PersonComparator());
System.out.println(Arrays.asList(people));
System.out.println("====改进①====");
Comparator<Person> comparator = (o1, o2)-> o1.getAge().compareTo(o2.getAge());
Arrays.sort(people,comparator);
System.out.println(Arrays.asList(people));
System.out.println("=====改进②=====");
//在奔雷中定义了比较的方法 只有一个方法
Arrays.sort(people,((o1, o2) -> o1.getAge().compareTo(o2.getAge())));
System.out.println(Arrays.asList(people));
System.out.println("=======使用方法引用=======");
Arrays.sort(people,Person::comparator);
//输出排过序的people数组
System.out.println(Arrays.asList(people));
}
}
//Comparator 比较器比较
class PersonComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge().compareTo(o2.getAge());
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Person {
private Integer age;
private String name;
public static int comparator(Person o1, Person o2) {
return o1.getAge().compareTo(o2.getAge());
}
}
更简单的例子
package com.hong.method;
import java.util.Arrays;
import java.util.List;
/**
* @Author hongCheng
* @Date 2021/4/25 20:22
* @Version 1.0
*/
public class StaticTest02 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(78,23,54,56,21,55);
//Comparator<? super E> c
//为list中的数据进行排序
list.sort(Integer::compareTo);
System.out.println(list);
}
}
对一个Integer列表进行排序,因为Integer中已经存在静态的比较方法compare(),因此可以直接用静态方法引用的方式来调用 ,运行结果为:
[21, 23, 54, 55, 56, 78]
2. 实例方法引用
实例方法引用,顾名思义就是调用已经存在的实例的方法,与静态方法引用不同的是类要先实例化,静态方法引用类无需实例化,直接用类名去调用。
package com.hong.method;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.function.Supplier;
/**
* @Author hongCheng
* @Date 2021/4/25 20:58
* @Version 1.0
*/
public class InstTest {
public static void main(String[] args) {
//获取外部类User对象
//lambda表达式
User user = new User();
user.setName("红橙");
System.out.println("====lambda表达式====");
Supplier<String> supplier = new Supplier<String>() {
@Override
public String get() {
return user.getName();
}
};
System.out.println(supplier.get());
//实例方法引用
System.out.println("=====实例方法引用=====");
Supplier<String> supplier1 = user::getName;
System.out.println(supplier1.get());
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class User {
private String name;
private Integer age;
}
3.对象方法引用
若Lambda参数列表中的第一个参数是实例方法的参数调用者,而第二个参数是实例方法的参数时,可以使用对象方法引用。
BiPredicate 代表了一个两个参数的boolean
值方法
BiPredicate的test()方法接受两个参数,x和y,具体实现为x.equals(y),满足Lambda参数列表中的第一个参数是实例方法的参数调用者,而第二个参数是实例方法的参数,因此可以使用对象方法引用。
package com.hong.method;
import java.util.function.BiPredicate;
/**
* @Author hongCheng
* @Date 2021/4/25 20:19
* @Version 1.0
*/
public class ObjectTest {
public static void main(String[] args) {
/**
* BiPredicate 是一个函数接口,接受两个参数并返回一个布尔值
*/
BiPredicate<String, String> biPredicate = new BiPredicate<String, String>() {
@Override
public boolean test(String s, String s2) {
return s.equals(s2);
}
};
boolean b = biPredicate.test("cx", "cx");
System.out.println(b);
System.out.println("=====lambda表达式方式=====");
System.out.println("=====改进①=====");
BiPredicate<String,String> biPredicate1 = (String s1,String s2)->{
return s1.equals(s2);
};
boolean b1 = biPredicate1.test("hong", "cheng");
System.out.println(b1);
System.out.println("=====改进①=====");
BiPredicate<String,String> biPredicate2 = (String s1,String s2)->{
return s1.equals(s2);
};
boolean b2 = biPredicate2.test("dong", "cheng");
System.out.println(b2);
System.out.println("=====改进②=====");
BiPredicate<String,String> biPredicate3 = (s1,s2)-> s1.equals(s2);
boolean b3 = biPredicate3.test("dong", "dong");
System.out.println(b3);
System.out.println("====对象方法引用====");
BiPredicate<String,String> biPredicate4 = String::equals;
boolean b4 = biPredicate4.test("shan", "dong");
System.out.println(b4);
}
}
4.构造方法引用
注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致。
构造方法引用与一般引用类似,只不过方法名为new
package com.hong.method;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.function.Supplier;
/**
* @Author hongCheng
* @Date 2021/4/25 21:28
* @Version 1.0
*/
public class NewTest {
public static void main(String[] args) {
Supplier<User> supplier = new Supplier<User>() {
@Override
public User get() {
return new User("冬冬",12);
}
};
System.out.println(supplier.get());
}
}