赞
踩
- public class LambdaDemo {
- public static void main(String[] args) {
- //开启一个线程
- new Thread(new Runnable() {
- @Override
- public void run() {
- System.out.println("新线程执行代码");
- }
- }).start();
- }
- }
分析:
当我们以 new Thread().start() 的方式启动一个线程时,我们做了如下3件事情:
- 定义了一个没有名字的类(匿名类)
- 这个类的参数,调用的是 Runnable 接口
- 我们通过 new Runnable(){...}的方式创建了这个类,并重写了该接口的 run() 方法
在这个示例中,其实我们关注的并不是 new Runnable() 这个过程,而是如下2点:
- run() 方法 (参数情况)
- {...}方法体中执行的代码
在以上Demo中,针对使用匿名内部类语法冗余的问题,JDK8推出了 Lambda 表达式。
- Lambda表达式体现的是函数式编程思想,只需要将要执行的代码放到函数中即可(函数就是类中的方法);
- Lambda表达式就是一个匿名函数,我们只需要将执行的代码放到 Lambda 表达式中即可。
Lambda省去面向对象的条条框框,Lambda的标准格式由3部分组成:
- (参数类型 参数名称) -> {
- 方法体;
- return 返回值;
- }
格式说明:
- (参数类型 参数名称):参数列表部分
- {...}:方法体,即要执行的代码部分
- ->:箭头,无实际含义,起到连接参数列表和方法体的作用
- 小括号中的参数类型可以省略。
- 如果小括号中只有一个参数,那么可以省略小括号。
- 如果大括号中只有一条语句,那么可以同时省略大括号、return关键字及语句分号。
- public class LambdaDemo {
- public static void main(String[] args) {
- //匿名内部类方式
- new Thread(new Runnable() {
- @Override
- public void run() {
- System.out.println("新线程执行代码了");
- }
- }).start();
-
- //体验Lambda表达式
- new Thread(() ->{
- System.out.println("Lambda表达式执行了");
- }).start();
- }
- }
☆ 可以简化匿名内部类,让代码更加精简
☆ Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。
1.无参数无返回值的Lambda表达式
①定义一个接口类ISwim,接口中定义一个抽象方法 swimming();
- /**
- * ISwim接口
- */
- public interface ISwim {
- //swimming()抽象方法
- public abstract void swimming();
- }
②定义一个方法 goSwimming(ISwim swim),注意该方法参数是一个接口类ISwim。然后 main 中调用该方法;
- public class LambdaDemo {
- public static void main(String[] args) {
- //1.使用匿名内部类方式
- goSwimming(new ISwim() {
- @Override
- public void swimming() {
- System.out.println("我是匿名内部类的游泳");
- }
- });
-
- //2.Lambda表达式方式
- goSwimming(()->{
- System.out.println("我是Lambda表达式的游泳");
- });
-
- }
-
- //goSwimming(ISwim swim) 方法
- public static void goSwimming(ISwim swim){
- swim.swimming();
- }
- }
-
- //测试结果:
- // 我是匿名内部类的游泳
- // 我是Lambda表达式的游泳
2.有参数有返回值的Lambda表达式
①定义一个接口类ISmoke,接口中定义一个具有返回值(int)的抽象方法 smoking();
- /**
- * ISmoke接口
- */
- public interface ISmoke {
- //smoking()抽象方法
- public abstract int smoking(String name);
- }
②定义一个方法 goSwimming(ISwim swim),注意该方法参数是一个接口类ISwim。然后 main 中调用该方法;
- public class LambdaDemo {
- public static void main(String[] args) {
- //1.使用匿名内部类方式
- goSmoking(new ISmoke() {
- @Override
- public int smoking(String name) {
- System.out.println("匿名内部类:抽了"+ name + "牌香烟");
- return 5;
- }
- });
-
- //2.使用Lambda表达式方式
- goSmoking((String name)->{
- System.out.println("Lambda表达式:抽了"+ name + "牌香烟");
- return 6;
- });
- }
-
- //有参数有返回值的Lambda
- public static void goSmoking(ISmoke smoke){
- int i = smoke.smoking("中华");
- System.out.println("返回值:"+i);
- }
- }
-
- //测试结果:
- // 匿名内部类:抽了中华牌香烟
- // 返回值:5
- // Lambda表达式:抽了中华牌香烟
- // 返回值:6
我们有一个List集合,集合中存放了 4个Person对象,Person对象中有 name,age,height 属性。对集合进行排序,我们会使用到 Collections 工具类中的 Collections.sort()方法。
sort()方法中传递的两个参数:1.list集合 2.Comparator 比较器。我们发现 Comparator 是一个接口,所以此处也可以使用 Lambda 表达式来替代匿名内部类。
- /**
- * Person实体类
- */
- public class Person {
-
- private String name;
-
- private int age;
-
- private int height;
-
- public Person(String name, int age, int height) {
- this.name = name;
- this.age = age;
- this.height = height;
- }
-
- 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 getHeight() {
- return height;
- }
-
- public void setHeight(int height) {
- this.height = height;
- }
-
- @Override
- public String toString() {
- return "Person{" +
- "name='" + name + '\'' +
- ", age=" + age +
- ", height=" + height +
- '}';
- }
- }
- public class CollectionsLambdaDemo{
-
- public static void main(String[] args) {
- List<Person> persons = new ArrayList<>();
- persons.add(new Person("刘德华",58,174));
- persons.add(new Person("张学友",56,176));
- persons.add(new Person("郭富城",54,171));
- persons.add(new Person("黎明",53,178));
-
- //1.匿名内部类,对集合进行排序
- Collections.sort(persons, new Comparator<Person>() {
- //年龄降序排序
- @Override
- public int compare(Person o1, Person o2) {
- return o2.getAge() - o1.getAge();
- }
- });
-
- for (Person person: persons) {
- System.out.println(person);
- }
-
- System.out.println("-----------------------------------");
-
- //2.Lambda表达式
- Collections.sort(persons,(Person o1,Person o2) ->{
- return o1.getAge() - o2.getAge();
- });
-
- for (Person person: persons) {
- System.out.println(person);
- }
- }
- }
-
- //测试结果:
- Person{name='刘德华', age=58, height=174}
- Person{name='张学友', age=56, height=176}
- Person{name='郭富城', age=54, height=171}
- Person{name='黎明', age=53, height=178}
- -----------------------------------
- Person{name='黎明', age=53, height=178}
- Person{name='郭富城', age=54, height=171}
- Person{name='张学友', age=56, height=176}
- Person{name='刘德华', age=58, height=174}
1.方法的参数或局部变量类型必须为接口!!!,才能使用Lambda
eg:局部变量类型:(Runnable是一个接口)
匿名内部类方式:
Runnable r = new Runnable(){
@override
public void run(){
System.out.println("xxx");
}
}
这种情况,你要来个局部变量,可以使用 Lambda表达式
Runnable r = ()-> System.out.println("xxx");2.接口中有且仅有一个抽象方法
JDK8中,只有一个抽象方法的接口称为函数式接口,我们就能使用 Lambda。
针对一个接口中,是否有大于一个抽象方法?JDK8为我们新增了一个注解:@FunctionalInterface。它能够帮助我们检测这个接口是不是只有一个抽象方法,如果有两个抽象方法,则会报错。
请跳转学习:Lambda表达式原理分析
1.所需的类型不一样
匿名内部类,需要的类型可以使类,抽象类,接口;
Lambda表达式,需要的类型必须是接口。
2.抽象方法的数量不一样
匿名内部类所需的接口中抽象方法的数量随意;
Lambda表达式所需的接口只能有一个抽象方法。
3.实现原理不同
匿名内部类是在编译后,会形成额外的一个 类名$0 的.class文件
Lambda 表达式实在程序运行的时候动态生成 .class 文件
当接口中只有一个抽象方法时,建议使用 Lambda 表达式;其他情况下,还是需要使用匿名内部类。
本目录为 JDK8新特性 学习目录,包含JDK8 新增全部特性的介绍。
如需了解,请跳转链接查看:我是跳转链接
博主写作不易,来个关注呗
求关注、求点赞,加个关注不迷路 ヾ(◍°∇°◍)ノ゙
博主不能保证写的所有知识点都正确,但是能保证纯手敲,错误也请指出,望轻喷 Thanks♪(・ω・)ノ
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。