lambda表达式的方法引用详解

背景

lambda表达式现在来说,已经在很多语言中出现过了,语法简单明了,功能强大,短短一行代码却能抵上jdk1.8之前的好几行,一般的lambda表达式写法资料已经很多了,本文不做介绍,今天我们要讨论的是其中一种读起来比较费解的表达式:::

就是两个冒号的表达式,String::new,System.out::println...等等,这种写起来很高大上,但是什么情况下可以使用这种表达式,我们怎么写呢?这就是本文的目的~

lambda expression

先来说结论:lambda的写法总共分为4中,分别为

1、类::静态方法

这个很好理解,但是需要说明的是,这种写法跟类.静态方法的调用是不相同的,或者说是没有关系的,这个是方法的调用(具体的使用方法),而我们今天说的是方法的引用,类似于“指针”,是指向了方法而已。

我们以比较学生的分数为例,进行代码说明:

public class Student {

    private int age;

    public Student(int age) {
        this.age = age;
    }

    public Student() {
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

然后用一个工具方法来定义比较规则

public class CompareUtil {

    public static int min(int a, int b) {
        return a - b;
    }

    //特意这样写的
    public int max(int a, int b) {
        return b - a;
    }
}

开始测第一种写法,对学生的年龄进行排序

public static void main(String[] args) {

    List<Student> al = Arrays.asList(
            new Student(10),
            new Student(24),
            new Student(14),
            new Student(4)
    );
    al.sort(CompareUtil::min);//表达式的第一种写法【类::静态方法】
    al.forEach(a-> System.out.println(a.getAge()));
}

得到结果

2、实例::实例方法

这种情况下,就是刚好需要传入的lambda表达式的格式符合某个类的实例方法,我们调用普通方法进行测试

public static void main(String[] args) {

        List<Student> al = Arrays.asList(
                new Student(10),
                new Student(24),
                new Student(14),
                new Student(4)
        );
        //实例方法,首先创建出实例
        CompareUtil compare = new CompareUtil();
        al.sort(compare::max);
//        al.sort(CompareUtil::min);
        al.forEach(a -> System.out.println(a.getAge()));
    }

得到结果

3、类::实例方法

这种情况下,比较特殊,因为完全取决于对调用着的要求,在lambda表达式中,第一个参数作为调用该实例方法,因此就要求第一个参数所代表的类里面有该方法,然后lambda表达式的其他参数就作为被调用方法的参数;从上面可以间接理解为:第一个参数调用实例方法,前提是该实例里面定义了方法,也就是类似于第二种模式:实例::实例方法,只不过实例采用了lambda第一个参数,因为在Student类中,加一个比较大小的方法,例子如下

public class Student {

    private int age;

    public Student(int age) {
        this.age = age;
    }

    public Student() {
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int max(Student p) {
        return -this.getAge() + p.getAge();
    }

然后我们就可以使用了

public static void main(String[] args) {

        List<Student> al = Arrays.asList(
                new Student(10),
                new Student(24),
                new Student(14),
                new Student(4)
        );
        //实例方法,首先创建出实例
//        CompareUtil compare = new CompareUtil();
//        al.sort(compare::max);
//        al.sort(CompareUtil::max);//编译报错,al.sort里面的lambda第一个参数student,显然学生类没有max方法
//        al.sort((s1, s2) -> s1.getAge() - s2.getAge());//这是原始的lambda表达式,所以第一个参数是student
        al.sort(Student::max);
//        al.sort(CompareUtil::min);
        al.forEach(a -> System.out.println(a.getAge()));
    }

4、构造方法

这种就比较好理解了,其实就是函数式接口supplier的使用,类型就是()->T,代表就是空参的输入,然后一个返回输出;这不就是空参的构造方法吗~

public String mixString(Supplier<String> a) {
    return a.get() + "mix";
}

调用

MethodRef2 methodRef2 = new MethodRef2();
System.out.println(methodRef2.mixString(String::new));

如果使用带参数的构造方法,那么就用方法来代表参数就行了

System.out.println(methodRef2.mixString2("abc", String::new));

虽然看上去一样的形式,但是我们点击new可以看到,调用的是String带有参数的构造方法,大家可以试一下。

以上就是lambda表达式的四种写法和使用场景,这下看scala或者jdk8源码不会觉得有懵逼的感觉了。。。

发布了12 篇原创文章 · 获赞 1 · 访问量 360

猜你喜欢

转载自blog.csdn.net/weixin_39800596/article/details/104430880