Java8 - Lambda Expression

本文参照于文章CSDN

Lambda表达式是java Stream的使用基础。

lambda表达式的语法由参数列表、->和函数体组成。函数体既可以是一个表达式,也可以是一个语句块。表达式执行后会返回执行结果。语句块中使用return将控制权转给调用者。表达式函数体省略return,适用于小型表达式,使得语法更加简洁。

参数可以无参或多个参数,参数可以指定数据类型,参数放在()中,无参的情况下()中为空,单参可以不用();函数体可以为表达式或语句块,单个表达式也可以放在语句块中。

接口:

public interface OnClickListener {
    void doOnClick();
}

无参Lambda表达式:

OnClickListener mListener = () -> System.out.println("do on Click");

OnClickListener mListener_ = () -> {
    System.out.println("插上电源");
    System.out.println("打开电视");
};

单个参数的情况下,可以省略(),多参数的情况不可以省略。

OnItemClickListener mItemListener = position -> System.out.println("position = [" + position + "]");

IMathListener mPlusListener = (x, y) -> x + y;

可以指定参数的类型,这时传入的参数类型必须匹配,否则编译错误。

IMathListener mSubListener = (int x, int y) -> x - y;

Lambda表达式中,修改方法体中引入的外部变量会报错,即Lambda表达式引用的是值而不是变量。

函数式接口是Java8中提供的一种特殊类型的接口,该接口中只定义了唯一的抽象方法,用作表达式的类型。下面是一个函数式接口的例子。

public interface IMathListener {
    int doMathOperator(int start, int plusValue);
}

下面用Lambda表达式声明了函数式接口IMathListener的实现。

IMathListener mSubListener = (x, y) -> x - y;
mMaxListener.doMathOperator(10, 5));// 其值5

对于函数接口而言,接口中唯一方法的命名并不重要了,只要方法签名和Lambda表达式的类别相匹配即可。但为了增加可读性,需要参数名称有意义。

现有的静态方法也可以支持Lambda表达式。

public class Math {
    public static int doIntPlus(int start, int plusValue) {
        return start + plusValue;
    }
}

关联:函数签名一样就可以,通过函数调用,直接生成了一个IMathListener对象。

IMathListener mPlusListener = Math::doIntPlus;

Lambda表达式都是静态类型的,在编译器编译,所以被引用的方法必须是静态方法。

每个用作函数接口的接口都应添加 @FunctionalInterface注释,该注释会强制 javac 检查一个接口是否符合函数接口的标准。如果该接口添加给枚举类型、类或函数不止一个的接口,javac会报错。

可以人工指定返回值数据类型。

overloadedMethod((x)->(String)y);

数据类型推导:Lambda表达式作为参数时,其类型由它的目标类型推导得出,规则如下。

  • 如果只有一个可能的目标类型,由相应函数接口里的参数类型推导得出;
  • 如果有多个可能的目标类型,由最具体的类型推导得出;
  • 如果有多个可能的目标类型且最具体的类型不明确, 则需人为指定类型。

总结:

使用Lambda表达式避免使用大量的匿名内部类,提高代码可读性。

进阶阅读 State of Lambda , Lambda Lib, Translation of Lambda Expression . 中文翻译参见 Lambda .

    原文作者:天长水远
    原文地址: https://zhuanlan.zhihu.com/p/37033392
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞