语法糖:lambda表达式
用法:
一.用来当做集合类的遍历
注意点:
1.无法使用continue,break等 用于一般foreach循环的;可用return 此处用法与continue等同;
2.无法在编译期,去改变循环外的对象的引用,或者是基本类型的值;
Integer[] a = new Integer[]{1,2,3,4,5};
List<Integer> b = Arrays.asList(a);
b.forEach(c->{
if (2==c){
return;
}
System.out.println("c = " + c);
});
Lambda与匿名内部类在访问外部变量时,都不允许有修改变量的倾向,即若:
1 2 3 4 5 6 7 8 |
|
则:
- 无法改变
final
量的值 - 不允许在Lambda表达式中修改使用的(外部)变量
相应的报错信息:
- Cannot assign a value to final variable
- Variable used in lambda expression should be final or effectively final
由是观之,我们将Lambda的这种变量捕获行为称之为值捕获更加确切。
在实际操作中,如果我们在Lambda体内或匿名内部类中要对外部的某些量进行操作,那么这种限制也是很容易被规避,因为即使数组是final
的(即该数组不能再指向其他数组对象),里面的值依旧可变。
所以我们只要将那个需要被操作的外部变量包装进一个数组即可:
final double[] a = {3.141592}; final double[] b = {3.141592}; DoubleUnaryOperator anotherDoubleUnaryOperator = x -> { a[0] = 2; // COOL b[0] = 3; // ALSO COOL return 0.0; };
也算是一个小技巧。
二.匿名内部类的实现
public static void main(String[] args) {
//不用写Runnable接口的匿名内部类
new Thread(()->System.out.println(11)).start();
//等于
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(1);
}
}).start();
}
三.和函数引用配合使用
/*
* 测试函数引用
*/
public class Test2 {
public static void main(String[] args) {
// 1.常规实现 匿名内部类
demo1(new A() {
@Override
public double f(double a, double b) {
return a * b;
}
});
//2.实现 -->a,b 类型被省去,return被省去
demo1((a,b)->a*b);
//函数引用
//在A接口的匿名内部类中,调用Test2.demo(a, b)
demo1(new A() {
@Override
public double f(double a, double b) {
return Test2.demo2(a, b);
}
});
demo1(Test2::demo2);
}
static void demo1(A a) {
double r = a.f(3.14, 23);
System.out.println(r);
}
static double demo2(double a,double b) {
return a*b;
}
}
package 示例;
/*
* 我是一个只有一个方法的接口
*/
public interface A {
double f(double a,double b);
}
结论:有趣,但可读性差,可读性更差的是函数编程