lambda表达式:函数式接口

来源:互联网 发布:编程软件图标 编辑:程序博客网 时间:2024/06/09 02:40

对于只包含一个抽象方法的接口,可以通过lambda表达式来创建该接口的对象。这种接口被称为函数式接口

例如:以Arrays.sort方法为例。该方法的第二个参数需要一个Comparator接口的实例。

Arrays.sort(words, (first, second) ->    Integer.compare(first.length(), second.length()));
该表达式背后,Arrays.sort方法会接收一个实现了Comparator<String>接口的类的实例。调用该对象的compare方法会执行lambda表达式中的代码。这些对象和类的管理完全依赖于如何实现,因此比传统的内部类效率更高。最好将一个lambda表达式想象成一个函数,而不是一个对象,并记住它可以被转换为一个函数式接口。

事实上,函数式接口的转换是在java中使用lambda表达式能做的唯一一件事。在其他支持函数文本的编程语言中,你可以声明像(String, String) -> int 这样的函数类型,声明这种类型的变量,并使用这些变量来保存函数表达式。但是在Java中是使用接口概念,没有能够使用函数类型。


不能将一个lambda表达式赋值给一个Object类型的变量,因为Object不是一个函数式接口。

任何一个lambda表达式都可以等价转换成现在所使用的API中对应的函数式接口。


可以在任意函数式接口上标注@FunctionalInterface注解,这样的好处是:编译器会检查该注解的实体,检查它是否是只包含一个抽象方法的接口;在javadoc页面也会包含一条声明,说明这个接口是一个函数式接口。


当一个lambda表达式被转换为一个函数式接口的实例时,请注意处理检查期异常。如果lambda表达式中可能会抛出一个检查期异常,那么该异常需要在目标接口的抽象方法中进行声明。例如,一下表达式会产生一个错误:

Runnable sleeper = () -> {            System.out.println("XXX");            Thread.sleep(1000);        };
错误是因为Thread.sleep(1000)可以抛出一个检查期InterruptedException

因为Runnable.run 不能抛出任何异常,所以这个赋值不合法。有2个方法解决:

1. 在lambda表达式中捕获异常。如下

Runnable sleeper = () -> {            System.out.println("XXX");            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }        };

2. 将lambda表达式赋给一个其抽象方法可以抛出异常的接口。例如,Callable接口的call方法可以抛出任何异常,可以将lambda表达式赋给Callable<Void>(要添加return null; 因为call抽象方法是有返回值的)。如下

Callable sleeper = () -> {            System.out.println("XXX");            Thread.sleep(1000);            return null;        };


0 0
原创粉丝点击