- lambda表达式函数体
- 条件表达式(?:)
- 转型表达式
Supplier<Runnable> c = () -> () -> {System.out.println("hi");};
Callable<Integer> c = flag ? (() -> 23) : (() -> 42);
Object o = () -> {System.out.println("hi");}; //非法
Object o = (Runnable) () -> {System.out.println("hi");};
词法作用域:
lambda不会引入一个新的作用域。
public class Hello {
Runnable r1 = () -> { System.out.println(this); };
Runnable r2 = () -> { System.out.println(toString()); };
public String toString() { return "Hello, world"; }
public static void main(String... args) {
new Hello().r1.run();
new Hello().r2.run();
}
}
Output:
Hello, world
Hello, world
lambda不可以掩盖其所在上下文中的局部变量,类似:
int i = 0;
int sum = 0;
for (int i = 1; i < 10; i += 1) { //这里会出现编译错误,因为i已经在for循环外部声明过了
sum += i;
}
变量捕获:
import java.util.function.Function;
public class Test3 {
int sum = 0;
public Function m() {
//int sum = 0;
Function<Integer, Integer> func= i -> {sum ++; return sum + i;};
sum++;
return func;
}
public static void main(String[] args) {
Test3 t = new Test3();
Function<Integer, Integer> func = t.m();
//t = null;
System.out.println(func.apply(9));
System.out.println(t.sum);
}
}
lambda只能捕获effectively final的局部变量,就是捕获时或捕获后不能修改相关变量。如果sum是m方法的局部变量,func不能修改该局部变量,因为m执行完就退出栈帧。同时这样也可以避免引起race condition,in a nutshell,lambda表达式对值封闭,对变量开放。
int sum = 0;
list.forEach(e -> { sum += e.size(); }); // Illegal, close over values
List<Integer> aList = new List<>();
list.forEach(e -> { aList.add(e); }); // Legal, open over variables
A race condition occurs when two or more threads can access shared data and they try to change it at the same time. Because the thread scheduling algorithm can swap between threads at any time, you don't know the order in which the threads will attempt to access the shared data.
public class Test3 {
public static void typeRef() {
// public String toUpperCase()
Function<String, String> func = String::toUpperCase;
System.out.println(func.apply("aaa"));
}