Java8 | 方法引用

一、什么是方法引用

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

方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖

要求:实现接口的抽象方法体的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致

使用操作符 :: 将类(或对象)与方法名分割开来

主要分为下面三种使用情况:

  1. 对象 :: 实例方法名
  2. 类 :: 静态方法名
  3. 类 :: 实例方法名

二、几种实例

准备一个 Employee 对象的 JavaBean

public class Employee {

	private int id;
	private String name;
	private int age;
	private double salary;
    
    // getter/setter 方法

}

1. 对象 :: 实例方法名
@Test
public void test1() {
    Consumer<String> consumer = new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    };

    // 此时方法引用中的参数也省略,因为和抽象方法中的参数一样,所以可以直接省略
    Consumer<String> consumer2 = System.out::println;
    consumer2.accept("陈磊是傻逼");
}

因为方法 void println(String x) 和接口中重写的方法体 void println(String s) 的形参列表和返回值类型都相同,所以直接用 void println(String x) 方法替代接口中的抽象方法,调用 println 方法的对象是 System.out,实例方法便是 println,此时不需要在后面跟参数,因为 println() 方法的形参列表和 accept() 的形参列表一样,所以此时的方法引用 println 后面的参数可以直接省略

@Test
public void test2() {
    Employee employee = new Employee(10, "陈磊");

    Supplier<String> supplier = new Supplier<String>() {
        // 此时 String getName() 和 String get() 方法类似
        @Override
        public String get() {
            return employee.getName();
        }
    };

    Supplier<String> supplier2 = employee::getName;
    System.out.println(supplier2.get());
}

此时方法 String getName() 和接口中抽象方法 String get() 的形参列表和返回值类型都相同,所以可以直接用 对象 :: 实例方法 的形式来简化,这里的对象是 employee,实例方法是 getName


2. 类 :: 静态方法

可以使用 类 :: 静态方法 的形式来作为抽象方法体的引用

@Test
public void test3() {
    Comparator<Integer> comparator = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1.compareTo(o2);
        }
    };
    System.out.println(comparator.compare(10, 20));

    // 使用 Lambda 表达式
    Comparator<Integer> comparator1 = (o1, o2) -> o1.compareTo(o2);
    System.out.println(comparator1.compare(10, 20));

    // 使用 Lambda 表达式和类的静态变量
    Comparator<Integer> comparator2 = (o1, o2) -> Integer.compare(o1, o2);
    System.out.println(comparator2.compare(10, 20));

    // 使用静态方法引用
    Comparator<Integer> comparator3 = Integer::compare;
    System.out.println(comparator3.compare(10, 20));
}

此时抽象方法体 int compareTo(Integer a) 可以转换成调用 Integer 的静态方法 int compare(int x, int y) 写成的 Lambda 表达式,而该 Lambda 表达式又可以转换成使用静态方法引用的格式

@Test
public void test4() {
    Function<Double,Long> function = new Function<Double, Long>() {
        @Override
        public Long apply(Double aDouble) {
            return Math.round(aDouble);
        }
    };
    System.out.println(function.apply(5.6));

    Function<Double, Long> function1 = aDouble -> Math.round(aDouble);
    System.out.println(function1.apply(5.7));

    Function<Double, Long> function2 = Math::round;
    System.out.println(function2.apply(5.8));
}

3. 类 :: 实例方法
@Test
public void test6() {
    BiPredicate<String,String> biPredicate = new BiPredicate<String, String>() {
        @Override
        public boolean test(String s, String s2) {
            return s.contentEquals(s2);
        }
    };

    BiPredicate<String, String> biPredicate1 = String::contentEquals;
}

需要注意的是,当函数式接口方法的第一个参数是需要引用方法的调用者,并且第二个参数是需要引用方法的参数(或无参数)时,可以使用 ClassName :: methodName 这样的来引用

这里的函数式接口方法是 boolean test(String s,String s2),其中的实现方法是用 s 调用 contentEquals(s2) 方法,而 boolean contentEquals(CharSequence cs) 表示使用 String 类型的参数来调用 contentEquals 方法,并返回 boolean 类型的值


三、构造器引用

可以把构造器引用赋值给定义的方法,要求构造器参数列表要与接口中抽象方法的参数列表一致,且方法的返回值即为构造器对应类的对象

格式:ClassName::new

public void test1(){
    Supplier<Employee> supplier = new Supplier<Employee>() {
        @Override
        public Employee get() {
            // 返回一个构造器
            return new Employee();
        }
    };

    Supplier<Employee> supplier1 = () -> new Employee();

    Supplier<Employee> supplier2 = Employee::new;
}
@Test
public void test2(){
    Function<Integer,Employee> function = new Function<Integer, Employee>() {
        @Override
        public Employee apply(Integer integer) {
            // 构造器参数列表和接口中抽象方法的参数列表一致,且抽象方法的返回值也是构造器对应类的对象
            return new Employee(integer);
        }
    };

    Function<Integer, Employee> function1 = integer -> new Employee(integer);

    Function<Integer, Employee> function2 = Employee::new;
}

四、数组引用

格式:type[] :: new

@Test
public void test4(){
    Function<Integer,String[]> function = new Function<Integer, String[]>() {
        @Override
        public String[] apply(Integer integer) {
            return new String[integer];
        }
    };

    Function<Integer, String[]> function1 = integer -> new String[integer];

    Function<Integer, String[]> function2 = String[]::new;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值