四、方法引用

方法引用

方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法。方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文。计算时,方法引用会创建函数式接口的一个实例。
注意方法引用是一个Lambda表达式,其中方法引用的操作符是双冒号::
有以下四种形式的方法引用(前两种常用):

类型 语法 对应的Lambda表达式
构造方法引用 类名::new (args) -> new 类名(args)
特定对象的实例方法引用 对象::实例方法名 (args) -> 对象.instMethod(args)
静态方法引用 类名::静态方法名 (args) -> 类名.staticMethod(args)
类的任意对象的实例方法引用 类名::实例方法名 (对象,args) -> 对象.instMethod(args)

实例


/**
 * 定义了 5 个方法作为例子来区分 Java 中 4 种不同方法的引用。
 */
public class Car {


    public static Car create(final Supplier<Car> supplier) {
        return supplier.get();
    }

    public static void collide(final Car car) {
        System.out.println("Collided " + car.toString());
    }

    public void follow(final Car another) {
        System.out.println("Following the " + another.toString());
    }
 
    public void repair() {
        System.out.println("Repaired " + this.toString());
    }
    //
    public void repair1(int a,String b) {
        System.out.println("a="+a+" ---- b="+b);
    }
    @FunctionalInterface
    interface TestRepairInterface
    {
        // 注意:入参比Car类的repair1方法多1个Car对象,除第一个外其它入参类型一致
        void repairInterface(Car c, int a,String b);
    }
}

测试

@Test
public void test1 (){
    /**
     * 构造方法引用
     * 类名::new 对应的Lambda:(args) -> new 类名(args)
     * 如 ArrayList<String>::new 等价于 () -> new ArrayList<String>()
     * 构造函数本质上是静态方法,只是方法名字比较特殊。
     *
     * 场景:适用于lambda表达式主体中仅仅调用了某个类的构造函数返回的实例。
     */

    //final Car car = Car.create(()-> new Car());
    final Car car1 = Car.create(Car::new );
    final List< Car > cars = Arrays.asList( car1);

    /**
     * 特定对象的实例方法引用
     * 实例::实例方法名 对应的Lambda: (args) -> inst.instMethod(args)
     * 与引用静态方法相比,都换为实例的而已
     *
     * 场景:适用于lambda表达式的主体中仅仅调用了某个对象的某个实例方法。
     */
    final Car police = Car.create( Car::new );
    //Consumer<Car> follow = (Car another) -> police.follow(another);
    Consumer<Car> follow = police::follow;
    cars.forEach( follow );

    /**
     * 静态方法引用
     * 类名::静态方法名 对应的Lambda:(args) -> 类名.staticMethod(args)
     * 和静态方法调用相比,只是把.换为::
     *
     * 场景:静态方法引用适用于lambda表达式主体中仅仅调用了某个类的静态方法
     */
    //Consumer<Car> collide = (Car car2) -> Car.collide(car2);
    Consumer<Car> collide = Car::collide;
    cars.forEach(collide);

    /**
     * 类的任意对象的实例方法引用(这种方法引用相对比较复杂)
     * 类名::实例方法名 对应的Lambda:(对象,args) -> 对象.instMethod(args)
     * Car类型的cars的任意car对象的实例方法repair
     *
     * 总结:类的任意对象的实例方法引用的特性为:
     * 1、方法引用的通用特性:方法引用所使用方法的入参和返回值与lambda表达式实现的函数式接口的入参和返回值一致;
     * 2、lambda表达式的第一个入参为实例方法的调用者,后面的入参与实例方法的入参一致
     */
    //无参
    cars.forEach( (repair1)->repair1.repair());
    cars.forEach( Car::repair);
    //有参
    Car.TestRepairInterface repairInterface1 =(repair2, a, b)->repair2.repair1(a,b);
    repairInterface1.repairInterface(new Car(),3,"4");
    Car.TestRepairInterface repairInterface2=Car::repair1;
    repairInterface2.repairInterface(new Car(),1,"2");



    /**
     * 再比如String类型的stringArray数组里面任意一个对象的实例方法compareToIgnoreCase
     * stringArray为一个String数组,lambda表达式(s1,s2)->s1.compareToIgnoreCase(s2)实现函数式接口的是Comparator接口
     */
    String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia" };
    //Arrays.sort(stringArray,(s1,s2)->s1.compareToIgnoreCase(s2));
    Arrays.sort(stringArray, String::compareToIgnoreCase);
    System.out.println(JSON.toJSONString(stringArray));

}
原文地址:https://www.cnblogs.com/bigfairy/p/14002058.html