lambda表达式
lambda表达式是一个可传递代码块,可以在以后执行一次或者多次
语法
参数->表达式
- 当只有一句表达式时
(String first, String second) -> first.length() - second.length();
- 当有多句表达式时
(String first, String second)->{
if(first.length() < second.length()) return -1;
else return 0;
}
- 当无参数时
()-> {
for(int i = 0; i < 10; i++)
System.out.println(i);
}
- 当参数类型可以被由上下文推到出时,参数类型可以省略
Comparator<String> comp = (first, second)->first.length() - second.length();
- 当只有一个参数,且此参数的类型可被推到出,可以省略参数类型以及小括号
ActionListener listener = event->System.out.println("The time is "+new Date());
6.无需指定返回类型
函数式接口
只有一个抽象方法的接口,当需要这种接口的对象时,可以提供一个lambda表达式。
e.g. Arrays.sort()方法,第二个参数需要一个Comparator实例,其是一个只有一个抽象方法的接口,所以可以提供一个lambda表达式
Arrays.sort(words, (first, second)->first.length() - second.length());
方法引用
对象或类名 :: 方法名
- object :: instanceMethod
System.out::println <-> x->System.out.println(x)
- Class :: staticMethod
Math :: pow <-> (x, y)->Math.pow(x, y)
这两种方法引用等价于提供参数的lambda表达式
- Class :: instanceMethod
String::compareToIgnoreCase <-> (x,y) -> x.compareToIgnoreCase(y)
这种方法引用,第一个参数会成为方法的目标
类似于lambda表达式,方法引用总是会转化为函数式接口的实例
可以在方法引用中使用this参数。this::equals <-> x.this.equals(x);
也可以使用super参数super::instanceMethod
会调用此方法的超类版本
变量作用域
lambda表达式有3个部分:代码块、参数、自由变量的值(这是指非参数而且不在代码块中定义的变量,且为不会改变的变量,否则并发执行不安全),在java中lambda表达式就是 闭包
- 合法的访问外部变量
public static void repeatMessage(String text, int delay){
ActionListener listener = event -> {
System.out.println(text);
Toolkit.getDefaultToolkit().beep();
};
new Timer(delay, listener).start();
}
repeatMessage("Hello", 1000);
- 不合法的访问外部变量(变量在代码块内部发生改变)
public static void countDown(int start, int delay){
ActionListener listener = event ->{
start--;
System.out.println(start);
};
new Timer(delay, listener).start();
}
- 不合法的访问外部变量(变量在代码块外部发生改变)
public static void repeat(String text, int ount){
for(int i = 1; i<=count;i++){
ActionListener listener = event ->{
System,out.println(i + ":" + text);
};
new Timer(1000, listener).start();
}
}
lambda表达式的体与嵌套快有相同的作用域,所以变量名不能冲突。
在lambda表达式中使用this关键字,是指创建这个lambda表达式的方法的this参数
public class Application(){
ActionListener listener = event ->{
System.out.println(this.toString());//this.toString()会调用Application的对象的toString方法
...
}
...
}