java8,作为一个从java5以来最具革命性的版本。
lambda表达式和 stream 是自Java语言添加泛型(Generics)和注解(annotation)以来最大的变化。
java8中一个非常重要的特性就是lambda表达式,我们可以把它看成是一种闭包,它允许把函数当做参数来使用,是面向函数式编程的思想,一定程度上可以使代码看起来更加简洁。
虽然看着很先进,其实Lambda表达式的本质只是一个"语法糖",由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能。本人建议不要乱用,因为这就和某些很高级的黑客写的代码一样,简洁,难懂,难以调试,维护人员想骂娘。
如果之前见到的话都会觉得,lambda就是一个匿名函数,我们可以这样来理解就好了,Lambda表达式就是为了使得我们的代码更加的简洁。
例如以前我们使用匿名内部类来实现代码:
//匿名内部类写法 new Thread(new Runnable() { @Override public void run() { System.out.println("内部类写法"); } }).start(); //使用lambda则更加简洁: new Thread(() -> System.out.println("lambda写法")).start();
lambda表达式语法
基本语法:
(parameters) -> expression
或
(parameters) ->{ statements; }
(1)左边括号:lambda的形参列表,就好比是我们定义一个接口,里面有一个抽象方法,这个抽象方法的形参列表。
(2)箭头:lambda的操作符,所以你看见这个箭头心中知道这是一个lambda表达式就可以了。
(3)右边lambda体:就好比是我们实现了接口中的抽象方法。
函数式接口
想要对lambda表达式有一个深入的理解,我们需要去认识另外一个知识点,那就是函数式接口。
比如我们的Runnable就是一个函数式接口,我们可以到源码中看看。
他主要有如下的特点:
(1)含有@FunctionalInterface注解
(2)只有一个抽象方法
函数式接口能够接受匿名内部类的实例化对象,换句话说,我们可以使用匿名内部类来实例化函数式接口的对象,而Lambda表达式能够代替内部类实现代码的进一步简化。
方法引用
3.1 对象::实例方法,将lambda的参数当做方法的参数使用
Consumer<String> sc = System.out::println; //等效 Consumer<String> sc2 = (x) -> System.out.println(x); sc.accept("618, 狂欢happy");
类::静态方法,将lambda的参数当做方法的参数使用
//ClassName::staticMethod 类的静态方法:把表达式的参数值作为staticMethod方法的参数 Function<Integer, String> sf = String::valueOf; //等效 Function<Integer, String> sf2 = (x) -> String.valueOf(x); String apply1 = sf.apply(61888);
类::实例方法,将lambda的第一个参数当做方法的调用者,其他的参数作为方法的参数。开发中尽量少些此类写法,减少后续维护成本。
//ClassName::instanceMethod 类的实例方法:把表达式的第一个参数当成instanceMethod的调用者,其他参数作为该方法的参数 BiPredicate<String, String> sbp = String::equals; //等效 BiPredicate<String, String> sbp2 = (x, y) -> x.equals(y); boolean test = sbp.test("a", "A");
构造函数
无参的构造方法就是类::实例方法模型,如:
Supplier<User> us = User::new; //等效 Supplier<User> us2 = () -> new User(); //获取对象 User user = us.get();
当有参数时:
//一个参数,参数类型不同则会编译出错 Function<Integer, User> uf = id -> new User(id); //或加括号 Function<Integer, User> uf2 = (id) -> new User(id); //等效 Function<Integer, User> uf3 = (Integer id) -> new User(id); User apply = uf.apply(61888); //两个参数 BiFunction<Integer, String, User> ubf = (id, name) -> new User(id, name); User 狂欢happy = ubf.apply(618, "狂欢happy");
总结
java8引入lambda表达式是接收了函数式编程语言的思想,例如scala之类的。
lambda表达式可以使代码看起来简洁,但一定程度上增加了代码的可读性以及调试的复杂性。