Java Lambda表达式详细介绍
Lambda简介
Lambda Lambda Lambda Lambda Lambda
Lambda基本语法
基本语法: (parameters) -> expression 或 (parameters) ->{ statements; }
- parameters:类似方法中的形参列表,这里的参数是函数式接口里的参数。
- ->:可以理解为 被用于
- 方法体:可以是表达式,也可以是代码,是函数式接口里方法的实现。
代码示例:
// 返回给定字符串的长度(隐含return语句) (String str) -> str.length() // 始终返回233的无参方法(隐含return语句) () -> 233 // 返回当前用户是否年龄大于20岁,返回一个boolean值(隐含return语句) (User user) -> user.getAge() > 20 // 包含多行表达式,需用花括号括起来,并使用return关键字返回 (int x, int y) -> { int z = x * y; return x + z; }
使用Lambda与传统写法对比
public class testMain { //执行Runnable方法 public static void process(Runnable r){ r.run(); } public static void main(String[] args) { //使用Lambda Runnable r1=()-> System.out.println("Hello Lambda"); //传统匿名类 Runnable r2 = new Runnable(){ public void run(){ System.out.println("Hello World 2"); } }; //打印 "Hello World 1" process(r1); //打印 "Hello World 2" process(r2); //利用直接传递的 Lambda 打印 "Hello World 3" process(() -> System.out.println("Hello World 3")); } }
Lambda表达式的基本使用
@FunctionalInterface interface NoParameterNoReturn { //注意:只能有一个抽象方法 void test(); } //无返回值一个参数 @FunctionalInterface interface OneParameterNoReturn { void test(String a); } //无返回值多个参数 @FunctionalInterface interface MoreParameterNoReturn { void test(int a, int b); } //有返回值无参数 @FunctionalInterface interface NoParameterReturn { int test(); } //有返回值一个参数 @FunctionalInterface interface OneParameterReturn { String test(String a); } //有返回值多参数 @FunctionalInterface interface MoreParameterReturn { int test(int a, int b); }
具体使用见以下示例代码
//没有参数没有返回值 NoParameterNoReturn noParameterNoReturn=()-> System.out.println("noParameterNoReturn"); noParameterNoReturn.test(); //没有参数但是有返回值 NoParameterReturn noParameterReturn=()->40; System.out.println("noParameterReturn: "+ noParameterReturn.test()); //一个参数没有返回值 OneParameterNoReturn oneParameterNoReturn=(name)-> System.out.println("Hello :" +name); oneParameterNoReturn.test("张三"); //一个参数和返回值 OneParameterReturn oneParameterReturn=(name)-> "Hello: "+name; System.out.println("oneParameterReturn : "+ oneParameterReturn.test("李四") ); //多参数没有返回值 MoreParameterNoReturn moreParameterNoReturn=(a,b)-> System.out.println("a+b= "+(a+b)); moreParameterNoReturn.test(10,20); //多参数和返回值 MoreParameterReturn moreParameterReturn=(a,b)-> a+b; System.out.println("moreParameterReturn: "+ moreParameterReturn.test(20,40));
输出结果如下:
Lambda 受检异常处理
简介
Lambda Lambda
代码示例
以一个简单代码为例,将10与List中每个元素相除并打印出结果
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6); integers.forEach(i -> System.out.println(50 / i));
这样看是不会有问题的,代码简洁。但是如果List中包含元素 0
,那么就会抛出异常: ArithmeticException: / by zero
有经验的小伙伴可能会立马给出解决方案,使用传统的try-catch来处理异常,代码如下:
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 0); integers.forEach(i -> { try { System.out.println(10 / i); } catch (ArithmeticException e) { System.err.println( "Arithmetic Exception occured : " + e.getMessage()); } });
使用try-catch解决了问题,但是失去了lambda表达式的精简,代码变得臃肿,想必并不是完美的解决方案。对于一些强迫症老哥来说,这种代码是绝对不能存活的,所以我们需要如下的解决方案。
解决方案
我们将会对抛出异常的函数进行包装,使其不抛出受检异常如果一个 FunctionInterface
的方法会抛出受检异常(比如 Exception
),那么该 FunctionInterface
便可以作为会抛出受检异常的 Lambda 的目标类型。我们定义如下一个 FunctionInterface
:
@FunctionalInterface interface UncheckedFunction<T, R> { R apply(T t) throws Exception; }
首先我们定义一个 Try
类,它的consumerWrapper方法:
public class Try { public static <T, E extends Exception> Consumer<T> consumerWrapper(Consumer<T> consumer, Class<E> clazz) { return i -> { try { consumer.accept(i); } catch (Exception ex) { try { E exCast = clazz.cast(ex); System.err.println( "Exception occured : " + exCast.getMessage()); } catch (ClassCastException ccEx) { throw ex; } } }; } }
然后在原先的代码中,我们使用 Try.consumerWrapper
方法来对会抛出受检异常的 Lambda 进行包装:
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 0); integers.forEach( Try.consumerWrapper( i -> System.out.println(50 / i), ArithmeticException.class));
此时,我们便可以选择是否去捕获异常( RuntimeException
)。这种解决方法下,我们一般不关心抛出异常的情况 。比如自己写的小例子,抛出了异常程序就该终止;或者你知道这个 Lambda 确实 100% 不会抛出异常。
如果您觉得本文不错, 欢迎关注,点赞,收藏支持 ,您的关注是我坚持的动力!