Lambda表达式初探

Lambda表达式初探

Lambda表达式是java8的重要更新,是被广大开发者期待已久的新特性。使用Lambda表达式可以用更简洁的代码来创建函数式接口的实例。
lambda表达式的类型,也被称为目标类型,Lambda表达式的目标类型必须是函数式接口。函数式接口代表只包含一个抽象方法的接口,函数式接口可以包含多个默认方法、类方法、但只能声明一个抽象方法。使用@FunctionalInterface注解可以在编译期间检查该接口是否是函数式接口。

1.Lambda表达式入门

在没有Lambda表达式之前,我们可能会用这样的方式去实现一个接口:

interface Add {
    int add(int a, int b);
}
public class LambdaDemo {
    public static void main(String[] args) {
        Add add = new Add() {
            @Override
            public int add(int a, int b) {
                return a + b;
            }
        };
        int result = add.add(3, 5);
        System.out.println(result);
    }
}

这样虽然也能达到目的,但是无形中就增加了代码量,也使得代码整体繁琐,难以阅读。但是使用Lambda就可以这样写:

@FunctionalInterface
interface Add {
    int add(int a, int b);
}
public class LambdaDemo {
    public static void main(String[] args) {
        Add add = (a, b) -> a + b;
        int result = add.add(3, 5);
        System.out.println(result);
    }
}

两者的结果是相同的,但是使用Lambda表达式实现接口时不需要new Xxx()这种繁琐的代码,不需要指出重写的方法名字,也不需要写出方法的返回类型。不仅大大减少了代码量,同时也使得代码清晰简洁,方便阅读。
从上面的例子中可以看出,当使用Lambda表达式替代匿名内部类创建对象时,Lambda表达式的代码块将会代替实现抽象方法的方法体,其表达式本身就相当于一个匿名方法,替代了匿名内部类的繁琐语法。
Lambda表达式由三部分组成:

  1. 形参列表:形参列表允许省略形参类型,如果形参列表中只有一个参数,圆括号也可以省略
  2. 箭头(->):英文画线号和大于符号
  3. 代码块:
    • 如果代码块只包含一条语句,可以省略代码块的花括号
    • 如果只有一条return语句,可以省略return关键字
    • 如果需要返回值且代码块中只有一条省略了return的语句,Lambda表达式会自动返回这条语句的值

2.方法引用与构造器引用:

使用方法引用和构造器引用可以使代码更加简化:

public class LambdaDemo2 {
    public static void main(String[] args) {
        // 1.引用类方法
        // 类名::类方法
        // 函数式接口中的被实现方法的全部参数传给该类方法作为参数
        Converter converter1 = value -> Integer.valueOf(value);
        System.out.println(converter1.valueOf("1"));

        Converter converter2 = Integer::valueOf;
        System.out.println(converter2.valueOf("1"));

        System.out.println("************************");

        // 2.引用特定对象的实例方法
        // 特定对象::实例方法
        // 函数式接口中的被实现方法的全部参数传给该类方法作为参数
        Converter converter3 = from -> "cnsuning.com".indexOf(from);
        System.out.println(converter3.valueOf("i"));

        Converter converter4 = "cnsuning.com"::indexOf;
        System.out.println(converter4.valueOf("i"));

        System.out.println("************************");

        // 3.引用某类对象实例方法
        // 类名::实例方法
        // 函数式接口中被实现方法的第一个参数作为调用者,后面的参数全部传给该方法作为参数
        MyTest test1 = (a, b, c) -> a.substring(b, c);
        System.out.println(test1.test("cnsuning.com", 2, 8));

        MyTest test2 = String::substring;
        System.out.println(test2.test("cnsuning.com", 2, 8));

        System.out.println("************************");

        // 4.引用构造器
        // 类名::new
        // 函数式接口中被实现的方法的全部参数传给该构造器作为参数
        MyTest2 test3 = username -> new Person(username);
        System.out.println(test3.test("jack"));

        MyTest2 test4 = Person::new;
        System.out.println(test4.test("jack"));

    }
}
@FunctionalInterface
interface Converter {
    Integer valueOf(String value);
}

@FunctionalInterface
interface MyTest {
    String test(String a, int b, int c);
}

class Person {
    private String username;

    public Person(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Person{");
        sb.append("username='").append(username).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

@FunctionalInterface
interface MyTest2 {
    Person test(String username);
}

3.Lambda表达式和匿名内部类的区别:

相同点:

  • Lambda表达式和匿名内部类都可以访问局部变量以及外部类的成员变量
  • Lambda表达式创建的对象和匿名内部类创建的对象都可以直接调用从接口中继承的默认方法

区别:

  • 匿名内部类可以为任意接口、抽象类、普通类创建实例,不管接口包含多少个抽象方法;但Lambda只能为函数式接口创建实例
  • 匿名内部类实现的抽象方法的方法体允许调用接口中定义的默认方法,但是Lambda不可以
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值