Java 8 lamda表达式

·  阅读 148

这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

前些日子在看Spring cloud gateway源码时,常看到lamda表达式。由于自己对lamda表达式不是很熟悉,特此重新学习。

前言

Lambda 表达式是 Java 8 发布的最重要新特性。它允许把函数作为一个方法的参数,传递进方法中去。使用 Lambda 表达式可以使代码变的更加简洁紧凑。需要注意的是lamda表达式的使用依赖于函数式接口。

为什么要使用lamda表达式

目前来说,使用lamda表达式最突出的优点在于简化代码,使代码变的更加简洁紧凑。

以最常见的线程创建为例:

  1. 传统方式

    public class Test {
        public static void main(String[] args) {
            Thread thread = new Thread(new RunTest());
            thread.run();
        }
    }
    ​
    ​
    class RunTest implements Runnable{
    ​
        @Override
        public void run() {
            System.out.println(123);
        }
    }
    复制代码
  2. 普通匿名内部类的方式

    public class Test {
        public static void main(String[] args) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("123");
                }
            });
            thread.run();
        }
    }
    复制代码
  3. lamda表达式方式

    public class Test {
    ​
        public static void main(String[] args) {
            Thread thread = new Thread(() -> {
                System.out.println(123);
            });
            thread.run();
        }
    }
    复制代码

通过比较可以发现,使用lamda表达式的方式代码更为简洁。

相关概念

lamda表达式格式

lamda表达式一般由以下格式构成:

(parameters) -> expression
或
(parameters) ->{ statements; }
复制代码

具体见以下示例

()->5; // 无参数,返回5
​
(int x,int y)->5*x+6*y; // 多参数,返回5*x+6*y的结果
​
x->5*x // 单参数,返回5*x的结果。当只有一个参数时,可以忽略括号和参数类型
复制代码

函数式接口

lamda表达式的使用依赖于函数式接口。所谓函数式接口,是指任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口。

代码示例如下所示:

@FunctionalInterface
public interface TestInterface {
    int test(int x);
}
复制代码

其中,为了避免后来人给这个接口添加函数后,导致该接口有多个函数,不再是函数式接口,我们可以在接口类的上方声明 @FunctionalInterface

用lamda实现函数式接口的方式如下:

public class Test {
    public static void main(String[] args) throws Exception {
        TestInterface test;
        test = x->{
            System.out.println(5*x);
            return 5*x;
        };
        int num = test.test(6);
        System.out.println(num);
    }
}
复制代码

由以上代码可见,对函数式接口赋值lamda语句,本质上是对接口方法进行实现。

方法引用

除了普通lamda表达式->类型外,还有另外一种写法,被称为方法引用

所谓方法引用,就是指如果一个方法的参数一致,返回值类型相同,那么就可以通过方法引用的方式对函数式接口进行赋值。

方法引用的格式如下:

// 类名::方法名
Integer::parseInt
复制代码

代码示例如下:

public class Test {
    public static void main(String[] args) throws Exception {
        TestInterface testInterface;
        testInterface = Integer::parseInt;
        int test1 = testInterface.test("123");
        // 上述代码等价于以下代码
        testInterface = x -> {
            return Integer.parseInt(x);
        };
        int test2 = testInterface.test("123");
    }
}
复制代码

除此之外,方法引用还有以下情况:

  • 构造器引用: 它的语法是Class::new,或者更一般的Class< T >::new实例如下:

    final Car car = Car.create( Car::new ); 
    final List< Car > cars = Arrays.asList( car );
    复制代码
  • 静态方法引用: 它的语法是Class::static_method,实例如下:

    cars.forEach( Car::collide );
    复制代码
  • 特定类的任意对象的方法引用: 它的语法是Class::method实例如下:

    cars.forEach( Car::repair );
    复制代码
  • 特定对象的方法引用: 它的语法是instance::method实例如下:

    final Car police = Car.create( Car::new ); cars.forEach( police::follow );
    复制代码
分类:
后端
标签:
分类:
后端
标签: