背景
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源码不会觉得有懵逼的感觉了。。。