您的位置:

Java Lambda表达式的使用

随着Java 8的发布,Lambda表达式成为Java编程语言中最重要的新特性之一。Lambda表达式提供了编写更为简洁、灵活的代码的方式,同时也让Java语言更加现代化。本文将全面介绍Java Lambda表达式的使用。

一、Lambda表达式的概念

Lambda表达式是一种匿名函数,它将方法作为一等公民(first-class citizen)。在Java中,Lambda表达式可以替换一些繁琐的代码,例如使用匿名内部类来实现单一方法接口。

Lambda表达式的基本格式如下:

(parameters) -> expression
或者
(parameters) -> { statements; }

其中:

  • parameters:参数列表
  • ->:Lambda表达式的分隔符
  • expression/ statements:Lambda表达式的方法体

Lambda表达式可以有0个或多个参数,参数类型可以显式声明,也可以根据上下文推断。如果一个Lambda表达式的方法体包含了多条语句,需要使用大括号将方法体括起来。如果方法体只有一条语句,可以省略大括号。Lambda表达式的返回值类型会根据上下文自动推断。

二、Lambda表达式的用法

1. 作为参数

在Java编程中,Lambda表达式通常用于函数式接口,即只有一个抽象方法的接口。Lambda表达式可以被赋予一个函数式接口类型的变量,被当作参数传递给方法,或者作为返回值。

代码示例:

首先定义一个函数式接口:

interface MyFunctionalInterface {
    void method();
}

使用Lambda表达式作为参数传递给方法:

public class LambdaAsParamExample {
    public static void main(String[] args) {
        doSomething(() -> System.out.println("do something"));
    }
    public static void doSomething(MyFunctionalInterface myFuncInterface) {
        myFuncInterface.method();
    }
}

这个例子中,使用Lambda表达式作为参数传递给了doSomething方法。Lambda表达式替换了一个匿名内部类。

2. 替代匿名内部类

在Java 8之前,在某些情况下需要使用匿名内部类来实现一个接口中的单一抽象方法。Lambda表达式可以让我们写出更为简洁的代码。

代码示例:

首先定义一个函数式接口:

interface MyFunctionalInterface {
    void method();
}

使用Lambda表达式替换匿名内部类:

MyFunctionalInterface myFuncInterface = () -> System.out.println("do something");

这个例子中,使用Lambda表达式替代了匿名内部类。对于只有一个抽象方法的接口,在使用匿名内部类时,通常都需要重写这个抽象方法,而使用Lambda表达式时则只需要写出方法体即可。这样做的好处在于,代码更为简洁、易读。

3. 使用Stream API

Stream API是Java 8中新增的API,可以让我们更方便地操作集合等数据结构。Lambda表达式在Stream API中起到了至关重要的作用。

代码示例:

首先定义一个学生类:

class Student {
    private String name;
    private int age;
    private int score;
    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    // getter and setter methods
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
    // toString() method
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}

使用Lambda表达式过滤出学生列表中成绩大于60分的学生:

public class LambdaAndStreamExample {
    public static void main(String[] args) {
        List<Student> studentList = Arrays.asList(
                new Student("Tom", 18, 70),
                new Student("Jerry", 19, 58),
                new Student("Lily", 17, 90),
                new Student("Lucy", 18, 64)
        );
        List<Student> collect =
                studentList.stream().filter(student -> student.getScore() > 60).collect(Collectors.toList());
        System.out.println(collect);
    }
}

这个例子中,使用Lambda表达式过滤出了成绩大于60分的学生。使用Lambda表达式可以大大减少代码量和阅读难度。

三、Lambda表达式的注意事项

1. Lambda表达式不是匿名类的实例

Lambda表达式与匿名类有相似之处,但也有不同。Lambda表达式不是匿名类的实例,其底层实现使用了invokedynamic指令。

2. Lambda表达式只能用于函数式接口

Lambda表达式只能用于函数式接口,即只有一个抽象方法的接口。当然,接口中可以有默认方法,静态方法等,但只有一个抽象方法是必须的条件。

3. Lambda表达式可以访问自由变量

自由变量是在Lambda表达式中引用的变量,但是其在Lambda表达式中没有被声明。Lambda表达式可以读取、修改自由变量。

4. Lambda表达式可以有可变长参数

Java中的Lambda表达式可以有可变长参数,其可变长参数会自动被包装成数组类型。

四、总结

本文详细介绍了Java Lambda表达式的使用方法。Lambda表达式可以使代码更为简洁、灵活,也能让Java语言更加现代化。虽然Lambda表达式不是匿名类的实例,但可以用于替换匿名内部类的使用。它不仅可以作为函数式接口的方法实现,也可以作为参数、返回值等。同时,Lambda表达式只能用于函数式接口,在使用时需要注意自由变量、可变长参数等问题。