在Java中,很多时候需要对一块代码进行传递。在JDK8版本以前,只能使用将代码块写入类中,使用的时候将类实例化对象作为参数传入。例如比较器的写法
public class comparator implements Comparator<String>{
public int compare(String a, String b) {
return a.length() - b.length();
}
public static void main(String[] args) {
String[] e = {"long", "middle", "sho"};
Arrays.sort(e, new comparator());
for(String s : e) {
System.out.println(s);
}
}
}
这里的比较器必须单独成类,然后将其对象当作Arrays.sort()
的参数,过程很繁琐,因为除了这一处参数外,cimparator
的类再不会在其他地方出现。基于这样的原因,在JDK8中提出了lambda表达式的新特性,用作一个简便的可传递的代码块。用lambda表达式对同样的程序进行整改后
public class comparator{
public static void main(String[] args) {
String[] e = {"long", "middle", "sho"};
Arrays.sort(e, (String a, String b) -> a.length() - b.length());
for(String s : e) {
System.out.println(s);
}
}
其中(String a, String b) -> a.length() - b.length()
代替了原先的cimparator
的类,简化了代码的逻辑。
lambda表达式的语法
(String a, String b) -> a.length() - b.length()
可以见得,主题为参数,箭头以及表达式。
- 表达式
- 当表达式仅有一行代码时,无需指定
return
返回类型,编译器会根据上下文自动推导得出。 - 如果表达式多余一行代码,需要使用
{}
扩括起。且需使用return
语句返回,而且return
语句必须出现在代码块的所有分支中。
- 参数
- 即使没有参数,仍要使用空括号。
- 如果只有一个参数,而且这个参数的类型可以通过上下文推导得出,则还可以省略小括号。
函数式接口
Java中有很多封装代码块的接口,比如前面的Comparator,还有ActionListener事件监听器,等等。这些接口可以在某些需要传入代码块的类中充当参数,这样的接口就是函数式接口。Java中并未重新为lambda表达式创建一个新的接口,而是使lambda表达式与这些函数式接口接口兼容,来解决参数传入问题。
方法引用
当已经存在你想要作为参数传递的某个代码块,但这个代码块是其他类中的某个方法。这个时候就可以通过方法引用的语法,将这个方法当参数传入。
public class compare {
public static int than(String a, String b) {
return a.length() - b.length();
}
}//已经存在的代码块
public static void main(String[] args) {
String[] e = {"long", "middle", "sho"};
Arrays.sort(e, compare::than);
for(String s : e) {
System.out.println(s);
}
}
其中compare::than
就是效用等同于lambda表达式的方法引用的语法。
可以使用一下两种方法作为lambda表达式的替代:
- object::instanceMethod
- Class::staticMethod