Java8语法糖之Lambda表达式的深入讲解

一、Lambda表达式简介

Lambda表达式,是Java8的一个新特性,也是Java8中最值得学习的新特性之一。(另一个新特性是流式编程。)

Lambda表达式,从本质上讲是一个匿名方法。可以使用这个匿名方法,实现接口中的方法。

功能:通常使用Lambda表达式,是为了简化接口实现的。关于接口实现可以有多种方式实现,例如:①设计接口的实现类、②使用匿名内部类。但是③使用lambda表达式,比这两种方式都简单。

要求:lambda表达式,只能实现函数式接口:即一个接口中,要求实现类必须实现的抽象方法,有且只有一个。

@FunctionalInterface注解 ,用在接口之前,用来判断接口是否是一个函数式接口。如果不是函数式接口会报错。功能类似于@Override。

二、Lambda表达式语法

lambda表达式本质上是一个匿名方法,因此再写lambda表达式时,不需要关心方法名是什么,也不需要关心返回值类型。只需要关心两部分:参数列表、方法体。

()参数部分:方法的参数列表,要求和实现的接口中的方法参数部分一致,包括参数的数量和类型。
{}方法体部分:方法的实现部分,如果接口中定义的方法有返回值,则在实现时,注意返回值的返回。
-> :分隔参数部分和方法体部分。

Lambda表达式基础语法:

(参数) ->{
 方法体
}

下面定义6种参数和返回值各不相同的函数式接口,分别使用lambda表达式对接口中的方法进行实现:

下面是针对上面6种函数式接口的lambda表达式实现。

/**
 * @Description:
 * @author Guoqianliang
 * @date 19:50 - 2021/2/15
 */
public class BasicSyntax {
 public static void main(String[] args) {
 // 1.实现无参数,无返回值的函数式接口
 NoneReturnNoneParameter lambda1 = () -> {
  System.out.println("这是无参,无返回值的方法");
 };
 lambda1.test();

 // 2.实现一个参数,无返回值的函数式接口
 NoneReturnSingleParameter lambda2 = (int a) -> {
  System.out.println("这是一个参数,无返回值的方法,参数a:" + a);
 };
 lambda2.test(10);

 // 3.实现多个参数,无返回值的函数式接口
 NoneReturnMutipleParameter lambda3 = (int a, int b) -> {
  System.out.println("这是多个参数,无返回值的方法,参数a=" + a + ",b=" + b);
 };
 lambda3.test(10, 20);

 // 4.实现无参数,有返回值有返回值的函数式接口
 SingleReturnNoneParameter lambda4 = () -> {
  System.out.println("这是无参数,有返回值的方法,返回值是:");
  return 10;
 };
 System.out.println(lambda4.test());

 // 5.实现一个参数,有返回值的函数式接口
 SingleReturnSingleParameter lambda5 = (int a) -> {
  System.out.println("这是一个参数,有返回值的方法,返回值是:");
  return a;
 };
 System.out.println(lambda5.test(10));

 // 6.实现多个参数,有返回值的函数式接口
 SingleReturnMutipleParameter lambda6 = (int a, int b) -> {
  System.out.println("这是多个参数,有返回值的方法,返回值是:");
  return a + b;
 };
 System.out.println(lambda6.test(1, 2));
 }
}

语法精简进阶:

  • 参数列表的参数类型可以省略。
  • 如果参数列表中的参数有且只有一个,可以省略小括号。
  • 如果方法体中只有一条语句,可以省略大括号。(注:如果这条语句是返回语句,省略了大括号后也要把return关键字省略)

三、函数引用

lambda表达式是为了简化接口。在lambda表达式中,不应该出现比较复杂的逻辑。如果需要处理的逻辑比较复杂,一般情况会单独写一个方法。在lambda表达式中直接引用这个方法即可。即引用一个已经存在的方法,使其代替lambda表达式完成接口的实现。

1.静态方法引用

语法:类::静态方法

在引用的方法后面,不要添加小括号。

引用的这个方法,参数(数量、类型)和返回值,必须要跟接口中定义的一致。

/**
 * @Description: 方法引用
 * @author Guoqianliang
 * @date 0:26 - 2021/2/16
 */
public class Lambda1 {

 private static interface Calculate {
  int calculate(int a, int b);
 }

 private static int calculate(int x, int y) {
  if (x > y) {
   return x - y;
  } else if (x < y) {
   return y - x;
  }
  return x + y;
 }

 public static void main(String[] args) {
  // 静态方法引用
  Calculate calculate = Lambda1::calculate;
  System.out.println(calculate.calculate(10, 20));
 }
}

2.非静态方法引用

语法:对象::非静态方法

在引用的方法后面,不要添加小括号。

引用的这个方法,参数(数量、类型)和返回值,必须要跟接口中定义的一致。

/**
 * @Description: 方法引用
 * @author Guoqianliang
 * @date 0:26 - 2021/2/16
 */
public class Lambda1 {

 private static interface Calculate {
  int calculate(int a, int b);
 }

 // 非静态方法
 private int calculate2(int a, int b) {
  if (a != b) {
   return a - b;
  }
  return a + b;
 }

 public static void main(String[] args) {
  // 非静态方法引用
  Calculate calculate2 = new Lambda1()::calculate2;
  System.out.println(calculate.calculate(10, 20));
 }
}

3.构造方法引用

语法:类名::new

可以通过接口中的方法的参数,区分引用不同的构造方法。

如果某一个函数式接口中定义的方法,仅仅是为了得到一个类的对象。此时就可以使用构造方法的引用,简化这个方法的实现。

/**
 * @Description: 构造方法引用
 * @author Guoqianliang
 * @date 11:20 - 2021/2/16
 */
public class Lambda2 {

 @FunctionalInterface
 private interface GetPersonWithNoneParameter {
  Person get();
 }

 @FunctionalInterface
 private interface GetPersonWithSingleParameter {
  Person get(String name);
 }

 @FunctionalInterface
 private interface GetPersonWithMutipleParameter {
  Person get(String name, int age);
 }

 private static class Person {
  String name;
  int age;

  public Person() {
   System.out.println("Person类的无参构造方法执行了");
  }

  public Person(String name) {
   this.name = name;
   System.out.println("Person类的有参构造方法执行了");
  }

  public Person(String name, int age) {
   this.name = name;
   this.age = age;
   System.out.println("Person类的两个参数的构造方法执行了");
  }
 }

 public static void main(String[] args) {
  // 1.使用lambda表达式,实现GetPersonWithNoneParameter接口
  GetPersonWithNoneParameter getPerson = Person::new;
  // 2.使用lambda表达式,实现GetPersonWithSingleParameter接口
  GetPersonWithSingleParameter getPerson2 = Person::new;
  // 3.使用lambda表达式,实现GetPersonWithMutipleParameter接口
  GetPersonWithMutipleParameter getPerson3 = Person::new;

  System.out.println(getPerson.get());
  System.out.println(getPerson2.get("树先生"));
  System.out.println(getPerson3.get("你好", 23));
 }
}

4.对象方法的特殊引用

使用lambda表达式实现某些接口时,如果lambda表达式中包含了某一个对象,此时方法体中,直接使用这个对象调用它的某一个方法就可以完成整体的逻辑。

/**
 * @Description: 对象方法的特殊应用
 * @author Guoqianliang
 * @date 11:54 - 2021/2/16
 */
public class Lambda3 {

 @FunctionalInterface
 private interface MyInterface {
  // String get(Person person);
  void set(Person person, String name);
 }

 private static class Person {
  private String name;

  public void setName(String name) {
   this.name = name;
  }

  public String getName() {
   return name;
  }
 }

 public static void main(String[] args) {
  Person p1 = new Person();
  p1.setName("小明");
//  逻辑实现只是为了获取到对象的名字
//  MyInterface lambda2 = Person::getName;
//  System.out.println(lambda2.get(p1));

  // 逻辑实现只是为了给对象的某些属性进行赋值
  MyInterface lambda1 = (x, n) -> x.setName(n);
  MyInterface lambda2 = Person::setName;
  lambda2.set(p1, "李华");
  System.out.println(p1.getName());
 }
}

四、Lambda表达式需要注意的问题

如果用到局部变量,默认会被声明为常量,不能发生值的改变。

/**
 * @Description:
 * @author Guoqianliang
 * @date 13:05 - 2021/2/16
 */
public class Lambda4 {
 public static void main(String[] args) {
  // 1.定义一个局部变量
  int x = 10;
  // 2.使用lambda表达式实现接口
  LambdaTest lambda = () -> {
   System.out.println("x=" + x);
  };
  // 3. 无法修改常量x
  // x=20;
 }
}

@FunctionalInterface
interface LambdaTest {
 void test();
}

总结

到此这篇关于Java8语法糖之Lambda表达式的文章就介绍到这了,更多相关Java8语法糖Lambda表达式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java8之lambda表达式基本语法

    lambda表达式,即带有参数的表达式,为更清晰地理解lambda表达式,先看如下例子: (1) class Student{ private String name; private Double score; public Student(String name, Double score) { this.name = name; this.score = score; } public String getName() { return name; } public Double getS

  • Java8深入学习系列(一)lambda表达式介绍

    前言 最近在学习java8,所以接下来会给大家介绍一系列的Java8学习内容,那么让我们先从lambda表达式开始. 众所周知从java8出现以来lambda是最重要的特性之一,它可以让我们用简洁流畅的代码完成一个功能. 很长一段时间java被吐槽是冗余和缺乏函数式编程能力的语言,随着函数式编程的流行java8种也引入了 这种编程风格.在此之前我们都在写匿名内部类干这些事,但有时候这不是好的做法,本文中将介绍和使用lambda, 带你体验函数式编程的魔力. 什么是lambda? lambda表达

  • Java8中Lambda表达式使用和Stream API详解

    前言 Java8 的新特性:Lambda表达式.强大的 Stream API.全新时间日期 API.ConcurrentHashMap.MetaSpace.总得来说,Java8 的新特性使 Java 的运行速度更快.代码更少.便于并行.最大化减少空指针异常. 0x00. 前置数据 private List<People> peoples = null; @BeforeEach void before () { peoples = new ArrayList<>(); peoples

  • Java8使用lambda实现Java的尾递归

    前言 本篇介绍的不是什么新知识,而是对前面讲解的一些知识的综合运用.众所周知,递归是解决复杂问题的一个很有效的方式,也是函数式语言的核心,在一些函数式语言中,是没有迭代与while这种概念的,因为此类的循环通通可以用递归来实现,这类语言的编译器都对递归的尾递归形式进行了优化,而Java的编译器并没有这样的优化,本篇就要完成这样一个对于尾递归的优化. 什么是尾递归 本篇将使用递归中最简单的阶乘计算来作为例子 递归实现 /** * 阶乘计算 -- 递归解决 * * @param number 当前阶

  • Java8新特性lambda表达式有什么用(用法实例)

    我们期待了很久lambda为java带来闭包的概念,但是如果我们不在集合中使用它的话,就损失了很大价值.现有接口迁移成为lambda风格的问题已经通过default methods解决了,在这篇文章将深入解析Java集合里面的批量数据操作(bulk operation),解开lambda最强作用的神秘面纱. 1.关于JSR335 JSR是Java Specification Requests的缩写,意思是Java 规范请求,Java 8 版本的主要改进是 Lambda 项目(JSR 335),其

  • Java8新特性Lambda表达式的一些复杂用法总结

    简介 lambda表达式是JAVA8中提供的一种新的特性,它支持Java也能进行简单的"函数式编程". 它是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数. 本文将介绍关于Java8 Lambda表达式的一些复杂用法,分享出来供大家参考学习,下面来一起看看详细的介绍: 复杂用法实例 传入数组ids,在list<Obj>上操作,找出Obj中id想匹配的,并且按

  • Java8中lambda表达式的应用及一些泛型相关知识

    语法部分就不写了,我们直接抛出一个实际问题,看看java8的这些新特性究竟能给我们带来哪些便利 顺带用到一些泛型编程,一切都是为了简化代码 场景: 一个数据类,用于记录职工信息 public class Employee { public String name; public int age; public char sex; public String time; public int salary; } 我们有一列此类数据 List<Employee> data = Arrays.asL

  • Java8 用Lambda表达式给List集合排序的实现

    Lambda用到了JDK8自带的一个函数式接口Comparator<T>. 准备一个Apple类 public class Apple { private int weight; private String color; public Apple(){} public Apple(int weight) { this.weight = weight; } public Apple(int weight, String color) { this.weight = weight; this.c

  • Java8学习教程之lambda表达式语法介绍

    前言 相信大家都知道,在Java8 中引入了 lambda 表达式,从行为参数化的角度,在使用时,将行为作为参数,去除包围在外层的不必要的类声明,使代码更加简洁. lambda 表达式的语法 lambda 表达式由参数,->,以及函数体三部分组成.其实函数体可以是表达式,也可以是语句.语句应该包含在{} 里,而表达式不能. lambda 表达式举例 (List<String> list) -> list.isEmpty() // 布尔类型表达式 () -> new Apple

  • Java8新特性之Lambda表达式浅析

    说到java 8,首先会想到lambda(闭包)以及虚拟扩展方法(default method),这个特性早已经被各大技术网站炒得沸沸扬扬了,也是我们java 8系列开篇要讲的第一特性(JEP126 http://openjdk.java.net/jeps/126),jdk8的一些库已经应用了lambda表达式重新设计了,理解他对学习java 8新特性有着重要的意义. 一.函数式接口 函数式接口(functional interface 也叫功能性接口,其实是同一个东西).简单来说,函数式接口是

随机推荐