在lambda表达式下的方法引用

时间:2021-7-4 作者:qvyue

方法引用

一、什么是方法引用

  • 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!
  • 方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
  • 要求:实现接口的抽象方法的參数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!
  • 格式:使用操作符 “:” 将类(或对象)与方法名分隔开来。
  • 如下三种主要使用情况:
    • 对象::实例方法名
    • 类::静态方法名
    • 类::实例方法名

二、使用情境

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!

三、使用格式

类(或对象):: 方法名

四、使用方法

1. 对象::实例方法名

1.1.1 代码演示(对象::实例方法名)
//情况一:
//对象::实例方法
//Consumer      中的void accept(T t)
//PrintStream   中的void println(T t)
@Test
public void test1() {
    //Lambda表达式使用
    Consumer con1 = str -> System.out.println(str);
    con1.accept("北京");
    
    System.out.printn("****************");
    //方法引用的使用
    PrintStream ps = System.out;
    Consumer con2 = ps::println;
    con2.accept("beijing");
}
1.1.2 代码解读

由前面的定义可知,当要传递给Lambda体的操作,已经有实现的方法了,就可以使用方法引用。

那么上面的代码当中Consumer的accept(T t)方法要执行的是println()语句,可是我们发现println()语句早就已经有实现的方法了,那就是Sysout.out

所以,我们发现这代码示例符合方法引用的定义,即要传递给Lambda体的操作,已经有实现的方法。由此,我们的方法引用也就顺势出现。我们的println()语句不是早就已经有实现的方法了吗?好,我们就用println()语句的对象去调用,即 PrintStream ps = System.out;

有了这个对象,就要用这个对象去调用其相应的方法,即用ps对象去调用它自己的println()方法。

语句产生 ps::println;

1.2.1 代码演示(对象::实例方法名)
//Supplier中的T get()
//Employee中的String getName()
@Test
public void test2(){
    //创建一个employee对象(这个pojo是我自己写的一个员工对象)
    //1001是ID
    //Tom是名字
    //23年龄
    //5600是薪水
    Employee emp = new Employee(1001,"Tom",23,5600);
    
    //Lambda表达式使用
    Supplier sup1 = () -> emp.getName();
    System.out.println(sup1.get());
    
    System.out.print1n("**************");
    
    //方法引用的使用
    Supplier sup2 = emp::getName;
    System.out.println(sup2.get());
}
1.2.2 代码解读

在使用了Lambda表达式的代码中我们发现,Supplier这个类的一个无参方法要执行 emp.getName(),但是我们发现,这个方法在emp这个对象本身内部就已经被实现了。由前面的定义可知,当要传递给Lambda体的操作,已经有实现的方法了,就可以使用方法引用。因此,我们就可以用相应的对象去调用其对应的方法,以此替换Supplier方法。

语句产生 emp::getName;

2. 类::静态方法名

2.1.1 代码演示
//情况二:          类::静态方法
//Comparator中的  int compare(T t1,T t2)
//Integer中的     int compare(T t1,T t2)
@Test
public void test3(){
    //使用lambda表达式的写法
    Comparator com1 = (t1,t2) -> Integer.compare(t1,t2);
    System.out.println(com1.compare(12,21));
    
    System.out.printn"(*****************");
    
    //使用方法引用之后的写法
    Comparator com2 = Integer::compare;
    System.out.print1n(com2.compare(12,3));
}
2.1.2 代码解读

在上述的代码中,我们可以看到Comparator将要执行一个带双参的方法,这个方法要做的事就是执行Integer.compare(t1,t2);可是我们发现,这个传递给Lambda体的操作,已经有实现的方法了,那就是Integer这个类中的compare方法,所以可以使用方法引用。

语法产生 Integer::compare;

2.2.1 代码演示
//Function中的    R apply(T t)
//Math中的        Long round(Double d)
@Test
public void test4() {
    //lambda表达式
    Function func1 = d -> Math.round(d);
    System.out.print1n(func1.apply(12.3));
    
    System.out.print1n("************");
    //方法引用
    Function func2 = Math::round;
    System.out.println(func2.apply(12.6));
}
2.2.2 代码解读

在上述的代码中,我们可以看到Function将要执行一个带参的方法,这个方法要做的事就是执行Math.round();可是我们发现,这个传递给Lambda体的操作,已经有实现的方法了,那就是Math这个类中的round方法,所以可以使用方法引用。

语法产生 Math::round;

3. 类::实例方法名

3.1.1 代码演示
//情况三:类::实例方法(有难度)
// Comparator中的int comapre(T t1,T t2)
// String中的int t1. compareTo(t2)
@Test
public void test5() {
    //使用Lambda表达式演示
    Comparator com1 = (s1,s2) -> s1.compareTo(s2);
    System.out.print1n(com1.compare("abc","abd"));
    
    System.out.println("***************");
    //使用方法引用的演示
    Comparator com2 = String::compareTo;
    System.out.println(com2.compare("abd","abm"));
}
3.1.2 代码解读

在上述的代码中,我们可以看到Comparator将要执行一个带双参的方法,这个方法要做的事就是执行s1.compareTo(s2);可是我们发现,这个传递给Lambda体的操作,已经有实现的方法了,那就是String这个类中的compareTo方法,所以可以使用方法引用。

语法产生 String::compareTo;

3.2.1 代码演示
//BiPredicate中的     boolean test(T t1, T t2);
//String中的          boolean t1.equals(t2)
@Test
pub1ic void test6() {
    //使用Lambda表达式
    BiPredicate pre1 = (s1,s2) -> s1.equals(s2);
    System.out.print1n(pre1.test("abc","abc"));
    
    System.out.println("***************");
    
    //使用方法引用
    BiPredicate pre2 = String::equals;
    System.out.println(pre2.test("abc","abc"));
}
3.2.2 代码解读

在上述的代码中,我们可以看到BiPredicate将要执行一个带双参的方法,这个方法要做的事就是执行s1.equals(s2);可是我们发现,这个传递给Lambda体的操作,已经有实现的方法了,那就是String这个类中的equals方法,所以可以使用方法引用。

语法产生 String::equals;

@Test
public void test() {
    //创建一个employee对象(这个pojo是我自己写的一个员工对象)
    //1001是ID
    //Jerry是名字
    //23年龄
    //6000是薪水
    Employee employee = new Employee(1001,"Jerry",23,6000);
    //使用Lambda表达式
    Function func1 = e -> e.getName();
    System.out.println(func1.apply(employee));
    
    System.out.println("***************");
    //使用方法引用
    Function func2 = Employee::getName;
    System.out.println(func2.apply(employee));
}

4. 构造器引用

4.1 代码演示
//构造器引用
//Supplier中的            T get()
//Employee的空参构造器:   Employee()
@Test
pub1ic void test1(){
    //正常写法
    Supplier sup = new Supplier() {
        @override
        public Employee get() {
            return new Emp1oyee();
        }
    };
    
    //使用lambda表达式的写法
    Supplier sup1 = () -> new Employee();
    
    //使用构造器引用的写法
    Supplier sup2 = Employee::new;
}
4.2 代码演示
//Function中的                R apply(T t)
//Employee的带参构造器:       Employee(int id)
@Test
public void test2(){
    
    //使用lambda表达式的写法
    Function func1 = id -> new Employee(id);
    Employee employee = func1.apply(1001);
    System.out.print1n(employee);
    
    //使用构造器引用的写法
    Function func2 = Employee::new;
    Employee employee1 = func2.apply(1002);
    System.out.print1n(emp1oyee1);
}
4.3 代码演示
//BiFunction中的              R apply(T t,U u) 
//Employee的带双参构造器:      Employee(int id,String name)
@Test
public void test(){
    //使用lambda表达式的写法
    BiFunction func1 = (id,name) -> new Employee(id,name)
    System.out.print1n(func1.app1y(1001,"Tom"));
    
    //使用构造器引用的写法
    BiFunction func2 = Employee::new;
    System.out.print1n(func2.app1y(1002,"Tom"));
}

5. 数组引用

5.1 代码演示
//数组引用
//如果将数组看作一个特殊的类,那就和构造器引用的使用没有什么区别
//Function中的R apply(T t)
@Test
public void telt4(){
    
    //使用lambda表达式的写法
    Function func1 = length -> new String[length];
    String[] arr1 = func1.apply(5);
    System.out.println(Arrays.toString(arr1));
    
    //使用构造器引用的写法
    Function func2 = String[]::new;
    String[] arr2 = func2.apply(10);
    System.out.println(Arrays.tostring(arr2));
}
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。