在java8中,增长了函数接口、Lambda和方法引用,使得建立函数对象变得很容易高效,本文经过情景引入,具体说明一下使用Lambda表达式建立接口对象是如何提升编程效率的。固然文中的所涉及的并不是Lambda的所有使用场景。java
咱们已有共识:Java是面向对象的编程语言,若是咱们调用任何一个对象的方法,并往方法中传递参数,参数必须是类或接口的对象或者是基本类型变量。
按照这个共识,咱们看下面的代码:编程
//定义一个接口 interface Example{ //接口中只定义了一个抽象方法 void add(Integer a,Integer b); } //接口的实现类 class ExampleImpl implements Example { @Override public void add(Integer a, Integer b) { System.out.println("a+b=" + (a + b)); } } //测试类 public class TestLambda { //测试类中定义了一个方法,并规定了接收参数的类型 public void test(Example example) { example.add(1, 1); } public static void main(String[] args) { //声明一个接口类型的变量并经过接口实现类实例化 Example example = new ExampleImpl(); //main方法中调用本身类的其余方法必须先建立该类的对象,经过对象调用 TestLambda testLambda = new TestLambda(); //调用test,并把实例好的对象传给test testLambda.test(example); } }
本地运行,控制台显示结果为:a+b=2。固然结果不重要。看懂了上述代码,思考一下,代码能否精简,提升执行效率。
观察得出:设计模式
接下来在上面的代码基础上,咱们使用匿名类替换实现类,使得代码进一步精简,代码以下:编程语言
//定义一个接口 interface Example{ //接口中只定义了一个抽象方法 void add(Integer a,Integer b); } //去掉了接口的实现类 //测试类 public class TestLambda { //测试类中定义了一个方法,并规定了接收参数的类型 public void test(Example example) { example.add(1, 1); } public static void main(String[] args) { //main方法中调用本身类的其余方法必须先建立该类的对象,经过对象调用 TestLambda testLambda = new TestLambda(); //调用test,并把Example类型的匿名类对象传给方法 testLambda.test(new Example(){ @Override public void add(Integer a, Integer b) { System.out.println("a+b=" + (a + b)); } }); } }
使用匿名类,咱们精简了代码,还能不能更加精简呢?
匿名类知足了传统面向对象的设计模式对函数对象的需求,可是,匿名类的繁琐使得Java中进行函数编程的前景变得十分黯淡。咱们平时的方法函数如同简单函数f(x),像这种f(t(x))的复合函数不常见。所谓函数式编程就是将函数(一段操做)做为一个基本单位进行传递。之前的Java中参数只能是具体的变量,函数式编程打破这一规范,能够将整个方法做为一个参数传递。
下面咱们使用Lambda表达式,进一步精简代码:ide
//定义一个接口 interface Example{ //接口中只定义了一个抽象方法 void add(Integer a,Integer b); } //去掉了接口的实现类 //测试类 public class TestLambda { //测试类中定义了一个方法,并规定了接收参数的类型 public void test(Example example) { example.add(1, 1); } public static void main(String[] args) { //main方法中调用本身类的其余方法必须先建立该类的对象,经过对象调用 TestLambda testLambda = new TestLambda(); //调用test,并把Lambda表达式传给方法 testLambda.test((a,b)->System.out.println("a+b=" + (a + b))); } }
Lambda表达式代码:(a,b)->System.out.println("a+b=" + (a + b))
最终执行效果同上。这样咱们经过使用Lambda表达式达到了代码干净简洁,执行效率高效的目的。函数式编程
咱们前后经过匿名类和Lambda表达式对代码重构,使得代码精简,使用匿名类容易理解,可是使用Lambda表达式感受与咱们开头的共识向左,缘由是什么呢?这个表达式难道就是符合类型要求的对象?这个表达式到底是如何起做用的?我想你们必定存在不少疑问。
注意观察:定义的接口只有一个抽象方法。
疑问答案:在Java8中(向后兼容),造成了“带有单个抽象方法的接口是特殊的,值得特殊对待”的观念,这些接口被称为函数接口,Java容许利用Lambda表达式建立这些接口的实例。Lambda相似于匿名类的函数,可是比它简洁更多。Lambda表达式被称为函数对象。
类型推导:编译器利用一个被称为类型推导的过程,根据上下文推断出类型。首先代码案例中,testLambda.test()方法惟一(TestLambda类中没有重载的test方法),编译器会强制认为testLambda.test()方法中的实际参数类型即Lambda表达式类型为定义的形式参数类型Example,又因为接口只有一个抽象方法,Lambda表达式天然只能实现该抽象方法,Lambda表达式表达式中的参数类型天然就是接口中抽象方法的参数类型。函数
能写成Lambda的接口的条件:接口中有且仅有一个抽象方法。如本案例中的接口Example,若是出现多个抽象方法,编译器的类型推导会出错。测试
函数式接口可使用(不强求)注解@FunctionalInterface 进行强制规范
更多Lambda语法知识,可参考官方文档。spa