java基础知识——Lambda表达式

简介

函数式编程(Functional Programming)是把函数作为基本运算单元,函数可以作为变量,可以接收函数,还可以返回函数。历史上研究函数式编程的理论是Lambda演算,所以我们经常把支持函数式编程的编码风格称为Lambda表达式。Lambda 表达式,也可称为闭包,Java平台从Java 8开始提供支持。允许把函数作为一个方法的参数,传递进方法中使用,并且使用 Lambda 表达式可以使代码变的更加简洁紧凑。

语法格式

(parameters) -> expression
或
//个人建议用此格式,把内容写全,这样麻烦点,但易于读写、理解与维护
(parameters) ->{ statements; } 
  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
    故,主要有以下几种实例
// 1. 不需要参数,返回值为 5 
() -> 5 
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x 
// 3. 接受2个参数(数字),并返回他们的差值 
(x, y) -> x – y 
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)

FunctionalInterface

我们把只定义了单方法的接口称之为FunctionalInterface,用注解@FunctionalInterface标记。可以看到Comparator、Runnable、Callable都是单方法接口,且都有@FunctionalInterface注解(注:单方法是指只有一个抽象方法需要实现,不是只有一个方法)。接收FunctionalInterface作为参数的时候,可以把实例化的匿名类改写为Lambda表达式,能大大简化代码。以下是基本库自带的常用函数式接口
在这里插入图片描述

方法引用

除了Lambda表达式,我们还可以直接传入方法引用,所谓方法引用,是指如果某个方法签名和接口恰好一致(方法签名只看参数类型和返回类型,不看方法名称,也不看类的继承关系),就可以直接传入方法引用,至于这个方法,我们可以自己写,也可以是用类库中的方法。除了静态方法,实例方法,还可引用构造方法,格式为:类名::new,返回类型为实例。方法引用的三种方式:

  • object::instanceMethod
  • Class::staticMethod
  • Class::instanceMethod

在前 2 种情况中,方法引用等价于提供方法参数的 lambda 表达式。
对于第 3 种情况, 第 1 个参数会成为方法的目标。例如,String::compareToIgnoreCase 等 同于(x,y)-> x.compareToIgnoreCase(y)。

简单应用

//定义一个单方法接口
@FunctionalInterface
public interface People {
    public abstract void say(String string);
}

public class LambdaMain {
    public static void main(String[] args) {
    
        //java1.8以前的实现方法
        Speak("Hi!", new People() {
            @Override
            public void say(String string) {
                System.out.println(string);
            }
        });

        //有Lambda之后的实现方法
        Speak("Hi!",(String string)->{System.out.println(string);});

        //方法引用,第一种是自己写的静态方法,第二种是基本库的
        Speak("Hi!", LambdaMain::talk);
        Speak("Hi!",System.out::println);
    }
    //定义一个静态方法,要使用必须先实现People接口
    public static void Speak(String string, People people) {
        people.say(string);
    }
    //用于方法引用
    public static void talk(String string) {
        System.out.println(string);
    }
}

注意事项

  • Lambda 表达式主要用来定义与实现方法类型接口(单方法接口)。即在方法声明时,用一个接口代替形参,用调用方法时,传入一个Lambda表达式实参,用于实现该接口
  • Lambda 表达式免去了使用匿名方法的麻烦
  • Lambda 表达式只能引用标记了 final 的外层局部变量
  • 在方法引用中,实例方法有一个隐含的this参数。例如:String类的compareTo()方法在实际调用的时候,第一个隐含参数总是传入this,相当于静态方法:public static int compareTo(this, String o);
  • lambda 表达式只在某些分支返回一个值, 而在另外一些分支不返回值, 这是不合法的。例如,(int x)-> { if(x>= 0) return 1;} 就不合法。
  • 并不是必须使用@FunctionalInterface注解才是函数式接口,任何只有一个抽象方法的接口都是函数式接口。不过使用 @FunctionalInterface 注解确实是一个很好的做法,因为如果你无意中增加了另一个非抽象方法, 编译器会产生一个错误消息。 另外javadoc 页里会指出你的接口是一个函数式接口。
发布了59 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_22136439/article/details/104340929