Java 8引入的Lambda表达式

Java 8的一大亮点就是引入了Lambda表达式,使用它可以替代我们以前经常写的匿名内部类来实现接口。Lambda表达式本质是一个匿名函数。


Lambda表达式语法

比如(int a, inb) -> {return a+b;},这个本质上是一个函数:
一般的函数定义如下:

int add(int a, int b) {
	return a+b;
}

是有返回值,方法名,参数列表,方法体
而Lambda表达式函数,只有参数列表、方法体
( 参数列表 ) -> { 方法体 }
说明:
( ): 用来描述参数列表
{ }: 用来描述方法体
->: Lambda运算符,可以叫做箭头符号,或者goes to

Lambda和匿名内部类的等价写法

package study;

public class Lambda表达式 {
    public static void main(String[] args) {
        If1 if1 = (int a, int b) -> {
            System.out.println("有两个参数a=" + a + " b=" + b + ",无返回值");
        };
        if1.test(4, 5);
        // 上面的写法等价于下面匿名内部类的写法
//        If1 if1 = new If1() {
//            @Override
//            public void test(int a, int b) {
//                System.out.println("有两个参数a=" + a + " b=" + b + ",无返回值");
//            }
//        };
//        if1.test(4, 5);

        If2 if2 = (int a, int b) -> {
            return a + b;
        };
        System.out.println(if2.test(4, 5));
        // 上面的写法等价于下面匿名内部类的写法
//        If2 if2 = new If2() {
//            @Override
//            public int test(int a, int b) {
//                return a+b;
//            }
//        };
//        System.out.println(if2.test(4, 5));
    }
}

interface If1 {
    void test(int a, int b);
}

interface If2 {
    int test(int a, int b);
}

方法引用

有时候多个Lambda表达式实现函数是一样的话,我们可以封装成通用方法,以便于维护,这时候就可以用方法引用实现:
语法是:对象::方法
加入是static方法,可以直接 类名::方法
代码如下:

interface If1 {
    void test(int a, int b);
}

interface If2 {
    int test(int a, int b);
}

class LambdaUse {
    public static void main(String[] args) {
        LambdaUse lambdaUse = new LambdaUse();
        If2 if2 = lambdaUse::test1; // 使用方法引用将 lambdaUse 实例的 test1 方法赋值给 If2 接口的 test 方法
        // 上面那行方法引用等价于下面一行
//        If2 if2 = (a, b) -> lambdaUse.test1(a, b); // 使用 Lambda 表达式
        // 也等价于下面匿名内部类的写法
//        If2 if2 = new If2() {
//            @Override
//            public int test(int a, int b) {
//                return lambdaUse.test1(a, b);
//            }
//        };
        System.out.println(if2.test(5, 6)); // 调用If2接口的test方法,然后test方法引用了lambdaUse 实例的 test1 方法
    }

    public int test1(int a, int b) {
        return a + b;
    }

    public static int test2(int a, int b) {
        return a + b;
    }
}

构造方法引用

在 Java 8 中,方法引用(method reference)不仅仅可以引用已有的方法,也可以引用构造方法。这被称为构造方法引用(constructor reference)。构造方法引用使用 ClassName::new 的语法,可以用来创建类的实例。

DogService dogService = Dog::new;
System.out.println(dogService.getDog());

DogService2 dogService2 = Dog::new;
System.out.println(dogService2.getDog("小花", 2));

DogService dogService = Dog::new;

  • DogService 接口定义了一个无参数的 getDog 方法,返回一个 Dog 对象。
  • Dog::new 是对 Dog 类中无参数构造方法的引用。
  • 当你调用 dogService.getDog() 时,实际上等价于调用了 new Dog()。

DogService2 dogService2 = Dog::new;

  • DogService2 接口定义了一个有参数的 getDog 方法,接受 String 和 int 参数,返回一个 Dog 对象。
  • Dog::new 是对 Dog 类中带有 String 和 int 参数的构造方法的引用。
  • 当你调用 dogService2.getDog(“小花”, 2) 时,实际上等价于调用了 new Dog(“小花”, 2)。

上面代码可以被等价成下面代码:
对于 DogService:

DogService dogService = () -> new Dog();
System.out.println(dogService.getDog());

对于 DogService2:

DogService2 dogService2 = (name, age) -> new Dog(name, age);
System.out.println(dogService2.getDog("小花", 2));

并且 构造方法引用 Dog::new 能够自动识别适当的构造方法,并将其与函数式接口的抽象方法匹配。编译器根据参数类型和返回类型来进行匹配,从而简化代码并保持类型安全。
也就是

DogService dogService = () -> new Dog();
System.out.println(dogService.getDog());

DogService2 dogService2 = (name, age) -> new Dog(name, age);
System.out.println(dogService2.getDog("小花", 2));

两种情况都写成Dog::new ,他自动会识别并调用合适的构造方法。

@FunctionalInterface注解

这个注解是函数式接口注解,所谓函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法,为Lambda表达式量身设计的。
这种类型的接口也成为SAM接口,即Single Abstract Method interfaces。

特点:

  • 接口有且仅有一个抽象方法
  • 允许定义静态方法
  • 允许定义默认方法
  • 允许java.lang.Object中的public方法
  • 该注解不是必须的,如果一个接口符合“函数式接口”定义,那么加不加注解都没有影响,加上该注解能够让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionalInterface,那么编译器就会报错,相当于要遵守规范。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重剑DS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值