Java8 的 Lambda 表达式
Java 8 的一个大亮点是引入 Lambda 表达式,使用它设计的代码会更加简洁。Lambda 表达式其实是一个匿名函数。
一、演变过程
1. 普通方法的写法
定义一个 Hero 对象,存储英雄的属性
public class Hero implements Comparable<Hero> {
/**
* 英雄名
*/
public String name;
/**
* 血量
*/
public float hp;
/**
* 伤害
*/
public int damage.......
筛选出, 满足下面条件的英雄类
private static void filter(List<Hero> heros) {for (Hero hero : heros) {if (hero.hp > 100 && hero.damage < 50)
System.out.print(hero);
}
}
这种方式,如果筛选条件改变,需要重新再写一个方法,稍微麻烦一点。
2. 匿名方法的写法
定义一个接口,接口的方法是判断是否满足的条件。
public interface IHeroChecker {
/**
* 判断 Hero 是否满足条件
* @param h
* @return
*/
public boolean checker(Hero h);
}
写一个过滤方法,判断条件是调用 IHeroChecker 对象的 checker 方法,其实就是这个方法中要使用另一个类的方法。
private static void filter(List<Hero> heros,IHeroChecker checker) {for (Hero hero : heros) {if(checker.checker(hero))
System.out.print(hero);
}
}
// 匿名类对实现此判断方法
IHeroChecker checker = new IHeroChecker() {
@Override
public boolean checker(Hero h) {return (h.hp>100 && h.damage<50);
}
};
filter(heros,checker);
使用匿名类实现这个方法,再调用 filter 方法
3.Lambda 表达式的写法
使用 Lambda 表达式就不用写匿名类了,将匿名类演变成 Lambda 表达式;
1. 把匿名类外面的壳子去掉,只保留方法参数和方法体;
2. 参数和方法体之间加上符号 ->
3. 把 return 和 {} 去掉
4. 只有一个参数时可以去掉();
// 匿名类对实现此判断方法
IHeroChecker checker = new IHeroChecker() {
@Override
public boolean checker(Hero h) {return (h.hp>100 && h.damage<50);
}
};
filter(heros,h->h.hp>100 && h.damage<50);
二、与匿名方法关系
与匿名类概念相比较,Lambda 其实就是匿名方法,这是一种把方法作为参数进行传递的编程思想。java 执行时, 还是会将他变成匿名类的.
三、Lambda 表达式弊端
1. 可读性差,匿名类代码结构比较起来,Lambda 表达式一旦变得比较长,不好理解;2. 不便于调试,很难在 Lambda 表达式中增加调试信息;3. 版本支持, 在 JDK8 以后才有, 之前的版本不支持。
四、Lambda 表达式方法的引用
前面我们讲了,Lambda 表达式其实就是一个方法,把 {} 和 return 去掉了而已,那我们如果有现成的方法,用已有的方法代替它该怎么做
1. 引用静态方法
已经有了静态方法
public static boolean checker(Hero h) {return h.hp>100 && h.damage<50;}
在 Lambda 表达式中使用
filter(heros, h -> LambdaTest.checker(h) );
直接引用
filter(heros, LambdaTest::checker);
2. 引用对象的方法
引用 LambdaTest 对象中 testHero 方法
LambdaTest lambdaTest = new LambdaTest();
filter(heros, lambdaTest::testHero);
3. 引用容器对象的方法
在 Hero 对象中有
private boolean matched(){return (hp > 100 && damage < 50);
}
在 Lambda 表达式中使用
filter(heros, h -> h.matched());
直接引用
filter(heros, Hero::matched);
五、总结
可以认为 Lambda 表达式可以看做是一个方法,我们把这个方法直接可以传递到另一个方法中。