JDK新特性
Lambda表达式
什么是Lambda表达式
Lambda表达式是一个匿名代码块,用于简单的传递一段代码片段。
Lambda表达式标准格式
格式:(形式参数) -> {代码块}
- 形式参数
如果有多个参数,参数只见用逗号隔开;如果没有,留空即可- ->
由英文中画线和大于符号组成,固定写法。代表指向动作。- 代码块
是我们具体要做的事情,也就是我们以前写的方法体内容
// 组成Lambda表达式的三要素:形式参数,箭头,代码块
// 示例
new Thread(() -> System.out.println("这是一个示例")).start();
Lambda表达式的使用前提
- 有一个接口
- 接口中有且仅有一个抽象方法
理解Lambda表达式
定义一只接口(Eatable),里面定义一个抽象方法:void eat();表示吃这一个动作。
然后以实现类,匿名内部类,Lambda表达式分别实现一下小明吃饭了这一动作。
通用接口 Eatable.java
package demo01;/*** 定义吃接口** @author Anna.* @date 2024/3/31 22:35*/
public interface Eatable {/*** 吃** @param* @return void* @author Anna.* @date 2024/3/31 22:35*/void eat();
}
实现类方式实现
创建一个实现类(EatImpl)实现(Eatable)接口
package demo01;/*** 吃实现类** @author Anna.* @date 2024/3/31 22:37*/
public class EatImpl implements Eatable{@Overridepublic void eat() {System.out.println("通过实现类-小明吃东西了");}
}
测试代码
package demo01;import java.util.Arrays;/*** Demo01:* 定义一只接口(Eatable),里面定义一个抽象方法:void eat();表示吃这一个动作。* 然后以实现类,匿名内部类,Lambda表达式分别实现一下小明吃饭了这一动作。** @author Anna.* @date 2024/3/31 22:36*/
public class LambdaDemo01 {public static void main(String[] args) {// 通过实现类实现Eatable eat = new EatImpl();eat.eat();}
}
执行结果
匿名内部类方式实现
测试代码
package demo01;import java.util.Arrays;/*** Demo01:* 定义一只接口(Eatable),里面定义一个抽象方法:void eat();表示吃这一个动作。* 然后以实现类,匿名内部类,Lambda表达式分别实现一下小明吃饭了这一动作。** @author Anna.* @date 2024/3/31 22:36*/
public class LambdaDemo01 {public static void main(String[] args) {// 匿名内部类方式实现eat(new Eatable() {@Overridepublic void eat() {System.out.println("通过匿名内部类方式实现-小明吃东西了");}});}/*** 定义一个调用Eatable接口eat()的方法** @param eatable* @return void* @author Anna.* @date 2024/3/31 22:50*/private static void eat(Eatable eatable){eatable.eat();}
}
执行结果
Lambda表达式实现
测试代码
package demo01;import java.util.Arrays;/*** Demo01:* 定义一只接口(Eatable),里面定义一个抽象方法:void eat();表示吃这一个动作。* 然后以实现类,匿名内部类,Lambda表达式分别实现一下小明吃饭了这一动作。** @author Anna.* @date 2024/3/31 22:36*/
public class LambdaDemo01 {public static void main(String[] args) {// Lambda表达式实现eat(() -> {System.out.println("通过Lambda表达式实现-小明吃东西了");});}/*** 定义一个调用Eatable接口eat()的方法** @param eatable* @return void* @author Anna.* @date 2024/3/31 22:50*/private static void eat(Eatable eatable) {eatable.eat();}
}
执行结果
对比实现类,匿名内部类,Lambda表达式编译文件
通过实现类方式实现,会生成EatImpl.class文件
通过匿名内部类方式实现,会生成LambdaDemo01$1.class匿名内部类文件
通过Lambda方式实现,不会额外生成文件,实现字节码会动态生成
Lambda表达式的省略模式
省略规则:
- 参数类型可以省略,但是多个参数的情况下,不能只省略一个
- 如果参数有且仅有一个,那么小括号可以省略
- 如果代码块的语句只有一条,大括号和分号可以省略,甚至是return
测试代码
package demo02;import demo01.Eatable;/*** Demo02:* Lambda表达式省略模式** @author Anna.* @date 2024/3/31 22:36*/
public class LambdaDemo02 {public static void main(String[] args) {// 正常调用System.out.println("=========正常调用=========");eat(() -> {System.out.println("小明吃东西了");});sum((int x, int y) -> {return x + y;});sleep((String name) -> {System.out.println(name + "睡觉了");});// 省略模式System.out.println("=========省略模式=========");System.out.println("=========参数类型可以省略=========");sleep((name) -> {System.out.println(name + "睡觉了");});// 参数类型可以省略,但是多个参数的情况下,不能只省略一个System.out.println("=========参数类型可以省略,但是多个参数的情况下,不能只省略一个=========");sum((x, y) -> {return x + y;});// 如果参数有且仅有一个,那么小括号可以省略System.out.println("=========如果参数有且仅有一个,那么小括号可以省略=========");sleep(name -> {System.out.println(name + "睡觉了");});// 如果代码块的语句只有一条,大括号和分号可以省略System.out.println("=========如果代码块的语句只有一条,大括号和分号可以省略=========");sleep(name -> System.out.println(name + "睡觉了"));// 如果代码块的语句只有一条,且有返回值 return 也可以省略System.out.println("=========如果代码块的语句只有一条,且有返回值 return 也可以省略=========");sum((x, y) -> x + y);}/*** 定义一个调用Eatable接口eat()的方法** @param eatable* @return void* @author Anna.* @date 2024/3/31 23:11*/private static void eat(Eatable eatable) {eatable.eat();}/*** 定义一个调用Sumable接口sum()的方法** @param sumable* @return void* @author Anna.* @date 2024/3/31 23:11*/private static void sum(Sumable sumable) {System.out.println(sumable.sum(20, 30));}/*** 定义一个调用Sleepable接口sleep()的方法** @param sleepable* @return void* @author Anna.* @date 2024/3/31 23:11*/private static void sleep(Sleepable sleepable) {sleepable.sleep("小明");}
}
执行结果
Lamda表达式的方法引用
学习lamda千万不要注意方法,一定要关心方法的入参的个数和类型以及出参的类型,不要关注方法的名称
方法引用被分为了好几类:
- 静态方法引用 Class::methodName
- 实例方法引用 objInstance::methodName
- 引用类中的非静态方法:Class::methodName
- 引用类的构造方法:Class::new 其中Class就是类名,后面跟“::new”,这个是固定写法哈,即使为了new一个对象出来
Sumable.java
package demo3;public interface Sumable {int sum(int x, int y);
}
SumImpl.java
package demo3;public class SumImpl implements Sumable {@Overridepublic int sum(int x, int y) {return x + y;}
}
SumUtils.java
package demo3;public class SumUtils {public int sum(int x, int y) {return x + y;}
}
IEntityDo.java
package demo3;public interface IEntityDo {SumEntity init(int x, int y);
}
SumEntity.java
package demo3;public class SumEntity {private int x;private int y;public SumEntity(int x, int y) {this.x = x;this.y = y;}@Overridepublic String toString() {return "SumEntity{" +"x=" + x +", y=" + y +'}';}
}
LambdaDemo03.java
package demo3;/*** Demo03:* Lambda表达式方法引用** @author Anna.* @date 2024/3/31 22:36*/
public class LambdaDemo03 {public static void main(String[] args) {System.out.println("Lambda方法");sum(((x, y) -> x + y));System.out.println("静态方法引用");sum(Integer::sum);System.out.println("实例方法引用");Sumable sumable = new SumImpl();sum(sumable::sum);System.out.println("如果该接口有且仅有一个抽象方法,还可以进一步省略::内容");sum(sumable);System.out.println("引用类中的非静态方法");SumUtils sumUtils = new SumUtils();sum(sumUtils::sum);System.out.println("引用类的构造方法");init(SumEntity::new);}/*** 定义一个调用Sumable接口sum()的方法** @param sumable* @return void* @author Anna.* @date 2024/3/31 23:11*/private static void sum(Sumable sumable) {System.out.println(sumable.sum(20, 30));}/*** 定义一个调用EntityDo接口init()的方法** @param entityDo* @return void* @author Anna.* @date 2024/3/31 23:11*/private static void init(IEntityDo entityDo) {System.out.println(entityDo.init(20, 30));}
}
执行结果
Lambda表达式优缺点
Java 8中引入了lambda表达式,使得代码编写更加简洁、优雅。lambda表达式是一个匿名函数,可以作为参数传递给方法或者存储在变量中。在Java中使用lambda表达式可以有以下优点和缺点:
优点
- 代码简洁:使用lambda表达式可以减少冗余的代码量,使得代码更加简洁明了。特别是在编写只有一个抽象方法的接口时,可以将其替换为lambda表达式。
- 促进函数式编程:lambda表达式使得函数式编程成为可能。函数式编程强调函数的纯粹性和不可变性,有助于减少副作用和提高代码的可维护性。通过lambda表达式,我们可以将函数作为一等公民,并在不改变状态的情况下进行操作。
- 更好的代码复用:使用lambda表达式可以更方便地实现代码的复用。可以将一段逻辑封装在一个lambda表达式中,然后在多个地方使用。
- 并行处理能力:在Java 8之前,要实现多线程或并行处理需要编写大量的代码。使用lambda表达式可以方便地编写并行处理的代码,充分利用多核处理器的性能。
- 提升代码可读性:lambda表达式将逻辑封装在一个更加紧凑的形式中,使得代码更易读。通过命名良好的lambda表达式,可以使代码的意图更加清晰。
缺点
- 学习成本:lambda表达式是一个新的概念,在Java中引入了新的语法。对于初学者来说,学习和理解lambda表达式需要一些时间和努力。
- 可读性差:虽然lambda表达式可以提升代码的可读性,但是过于复杂的lambda表达式可能反而降低代码的可读性。尤其是当lambda表达式包含多个参数、多行代码或复杂的逻辑时,可读性会受到影响。
- 调试困难:由于lambda表达式是匿名函数,调试时可能会更加困难。在调试过程中,无法直接跟踪lambda表达式的执行路径,可能会增加调试的难度。
- 性能问题:lambda表达式的性能可能比传统的方法调用略差。虽然这个差距很小,但是在某些高性能场景下可能会有所影响。
总结:
lambda表达式是Java 8引入的一项强大的功能,对于简化代码、促进函数式编程、提升代码可读性和代码复用等方面都有很大的帮助。
然而,它也存在着一些学习成本高、可读性差、调试困难和性能问题等缺点。
在使用lambda表达式时,需要根据具体情况权衡利弊,选择合适的使用方式。
gitee源码
git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git