Java8InAction-行为参数化与Lambda
1、摘要
用更少的代码干更多的事,一直是程序员的追求。
但是很多时候,需求的变化,很容易让我们写出高度冗余的代码。
很多函数可能就是几句核心代码不一样,复制粘贴稍微改改就行。
行为参数化,就是把行为封装起来,然后作为参数传递。
策略模式就是一种行为参数化的实现,将行为封装在不同的类中,然后通过传递类来传递行为。
但是,为了封装行为而写一个类,有点大材小用,写了很多不必要的代码。
我们有没有一种能够直接传递行为的方法呢?
有,那就是Lambda表达式。它可以封装一个行为并可以进行传递。
Lambda为什么这么神奇呢?
实际上Lambda只能称得上是一个Java的语法糖,
它只是将我们创建Java类,生成Java对象的操作交给了JVM来实现,简化了我们的工作,
但是并没有添加新的特性,自己封装类做不到的它也做不到。
在JVM执行到lambda表达式时,它会根据上下文中的类型信息,将表达式绑定到一个接口(函数式接口),
然后,再使用动态生成字节码的方式,创建一个实现了该接口的类来封装表达式的功能,
最后,再创建该类的的一个对象。
2、行为参数化
阿拉丁神灯最近很烦躁,因为对许愿者的每一个愿望,神灯都要念一段长长的咒语。
先是要念咒语来激发神力,然后才能使用神力来实现愿望,最后还要念咒语收回神力。
可是,随着神力越来越强大,神灯需要念的咒语也越来越长了。
经常会出现念咒两小时,实现愿望两分钟的情况。
许愿者的每次都要等很久,差评愈来愈多了。
于是神灯去找了智慧之神。
public class Ald { void wish1(){ System.out.println("power activated!"); System.out.println("a"); System.out.println("power deactivated!"); } void wish2(){ System.out.println("power activated!"); System.out.println("b"); System.out.println("power deactivated!"); } void wish3(){ System.out.println("power activated!"); System.out.println("c"); System.out.println("power deactivated!"); } }
智慧之神看了神灯实现愿望后,说,你也太笨了吧,就不会发明一个自动咒语机嘛。
只用传入愿望就行了,咒语机自动念咒语。
public class Ald { void wish1(String a){ System.out.println("power activated!"); System.out.println(a); System.out.println("power deactivated!"); } }
使用了自动咒语机一段时间之后,神灯还是不太满意。
机器一次只能传入一个咒语,但是,好多愿望要好几个咒语才能实现。
因此,它又去找了智慧之神。
智慧之神不想跟他说话,并扔给他又一个咒语机。
interface wish{ public void handleWish(); } class wish1 implements wish{ @Override public void handleWish() { System.out.println("哇啦哇啦"); System.out.println("wish2!"); System.out.println("巴卡巴卡"); } } class wish2 implements wish{ @Override public void handleWish() { System.out.println("乌拉乌拉"); System.out.println("wish2!"); System.out.println("巴卡巴卡"); } } public class Ald { void wish1(wish a){ System.out.println("power activated!"); a.handleWish(); System.out.println("power deactivated!"); } }
。。。编不下去了。。。。还是看代码吧。。。
使用策略模式虽然更加的清晰了,但是,却不免要创建一些策略类,
对于不会反复使用的策略,还要建立一个类,是不大划算的。
interface wish{ public void handleWish(); } public class Ald { void wish(wish a){ System.out.println("power activated!"); a.handleWish(); System.out.println("power deactivated!"); } public static void main(String[] args) { Ald ald=new Ald(); ald.wish(new wish() { @Override public void handleWish() { System.out.println("乌拉乌拉"); System.out.println("wish2!"); System.out.println("巴卡巴卡"); } }); } }
使用匿名类可以简化建立类的代码。
interface wish{ public void handleWish(); } public class Ald { void wish(wish a){ System.out.println("power activated!"); a.handleWish(); System.out.println("power deactivated!"); } public static void main(String[] args) { Ald ald=new Ald(); ald.wish(() -> { System.out.println("乌拉乌拉"); System.out.println("wish2!"); System.out.println("巴卡巴卡"); }); } }
使用匿名表达式,则更进了一步,连方法名这些都简化了。
3、Lambda表达式
匿名表达式结构:
(param)->expression 或
(param)->{ sentences; }
函数式接口:
即只有一个抽象方法的接口(可以有多个默认方法)。
至于只有一个抽象方法,应该是为了便于绑定吧。毕竟匿名表达式只能以参数和返回值来区分。
因此一个匿名表达式可以绑定到多个函数式接口上,只要参数、返回值匹配。
java.util.function中定义了很多函数式接口,我们也能创建自己的函数式接口。
方法引用:
根据已有的方法来创建Lambda表达式。
这是在Lambda表达式中调用特定方法的一种便捷写法。
方法引用说明了在创建的Lambda中执行哪个方法。
主要有三类:
1、指向静态方法的方法引用
如 Integer::parseInt
指向构造器 ClassName::New(parameter)
2、指向类方法的方法引用
如 String::length
3、指向实例方法的方法引用
假设 a是一个对象,并且a是lambda表达式的一个参数,则可以使用方法引用来指向a的实例方法
(A a)->a.method; 或 (A a, B b)->a.mothod(b); 可改写为:
a::method
@FunctionalInterface interface Wish { void handleWish(); static void defaultHandleWish() { System.out.println("defaultHandleWish!"); } default public void defaultHandleWishNonStatic() { System.out.println("defaultHandleWishNonStatic"); } } class Wish1 implements Wish{ Wish1(){ System.out.println("New!"); }; public static void handleWish1() { System.out.println("handleWish1"); } @Override public void handleWish() { System.out.println("handleWish2"); } } public class Ald { void wish(Wish a){ System.out.println("power activated!"); a.handleWish(); System.out.println("power deactivated!"); } public static void main(String[] args) { Ald ald=new Ald(); Wish1 wish1=new Wish1(); ald.wish(Wish1::handleWish1); //指向静态方法,此时,a.handleWish();执行的是Wish1::handleWish1方法 ald.wish(Wish1::new); //指向构造器,此时,a.handleWish();执行的是Wish1的构造器方法 ald.wish(wish1::handleWish); //指向实例方法,此时,a.handleWish();执行的是wish1::handleWish方法 ald.wish(()-> System.out.println("handleWish3")); //lambda,此时,a.handleWish();执行的是System.out.println("handleWish3")语句 ald.wish(Wish::defaultHandleWish); //同样Lambda中也能执行接口的static方法 ald.wish(wish1::defaultHandleWishNonStatic); //执行接口中的默认方法 } }
New!
power activated!
handleWish1
power deactivated!
power activated!
New!
power deactivated!
power activated!
handleWish2
power deactivated!
power activated!
handleWish3
power deactivated!
power activated!
defaultHandleWish!
power deactivated!
power activated!
defaultHandleWishNonStatic
power deactivated!

浙公网安备 33010602011771号