Java22-day13【Lambda表达式(标准格式、练习、注意事项)、接口组成更新(默认-静态-私有方法)、方法引用(构造器)】

      

目   录

01_体验Lambda表达式

1.1、函数式编程思想概述

1.2、体验Lambda表达式

02_Lambda表达式的标准格式

1.3、Lambda表达式的标准格式

03_Lambda表达式练习1(抽象方法无参无返回值)

1.4、Lambda表达式的练习

04_Lambda表达式练习2(抽象方法带参无返回值)

05_Lambda表达式练习3(抽象方法带参带返回值)

06_Lambda表达式的省略模式

1.5、Lambda表达式的省略模式

07_Lambda表达式的注意事项

1.6、Lambda表达式的注意事项

08_Lambda表达式和匿名内部类的区别

1.7、Lambda表达式和匿名内部类的区别

09_接口组成更新概述

1.1、接口组成更新概述

10_接口中默认方法

1.2、接口中默认方法

11_接口中静态方法

1.3、接口中静态方法

12_接口中私有方法

1.4、接口中私有方法

13_体验方法引用

1.1、体验方法引用

14_方法引用符

1.2、方法引用符

15_引用类方法

1.3、Lambda表达式支持的方法引用

1.4、引用类方法

16_引用对象的实例方法

1.5、引用对象的实例方法

17_引用类的实例方法

1.6、引用类的实例方法

18_引用构造器

1.7、引用构造器


01_体验Lambda表达式

1.1、函数式编程思想概述

在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿数据做操作”。

面向对象思想强调“必须通过对象的形式来做事情”。

函数式思想则尽量忽略面向对象的复杂语法:“强调做什么,而不是以什么形式去做”。

而我们要学习的Lambda表达式就是函数式思想的体现。

1.2、体验Lambda表达式

案例需求:启动一个线程,在控制台输出一句话:多线程程序启动了。

实现方式1:(麻烦)

  • 定义一个类MyRunnable实现Runnable接口,重写run()方法
  • 创建MyRunnable类的对象
  • 创建Thread类的对象,把MyRunnable的对象作为构造参数传递
  • 启动线程

实现方式2:

  • 匿名内部类的方式改进

实现方式3:

  • Lambda表达式的方式改进

02_Lambda表达式的标准格式

1.3、Lambda表达式的标准格式

Lambda表达式的格式

  • 格式:(形式参数) -> {代码块}
  • 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可。
  • ->:由英文中画线和大于符号组成,固定写法。代表指向动作。
  • 代码块:是我们具体要做的事情,也就是以前我们写的方法体内容。

03_Lambda表达式练习1(抽象方法无参无返回值)

1.4、Lambda表达式的练习

Lambda表达式的使用前提:

  • 有一个接口。
  • 接口中有且仅有一个抽象方法。

练习描述

  • 无参无返回值抽象方法的练习。

练习1 操作步骤

  • 1.定义一个接口(Eatable),里面定义一个抽象方法:void eat();
  • 2.定义一个测试类(EatableDemo),在测试类中提供两个方法:

一个方法是:useEatable(Eatable e)

一个方法是主方法,在主方法中调用useEatable方法

04_Lambda表达式练习2(抽象方法带参无返回值)

练习描述

  • 有参无返回值抽象方法的练习。

练习2 操作步骤

  • 1.定义一个接口(Flyable),里面定义一个抽象方法:void fly(String s);
  • 2.定义一个测试类(FlyableDemo),在测试类中提供两个方法:

一个方法是:useFlyable(Flyable f)

一个方法是主方法,在主方法中调用useFlyable方法

05_Lambda表达式练习3(抽象方法带参带返回值)

练习描述

  • 有参有返回值抽象方法的练习。

练习3 操作步骤

  • 定义一个接口(Addable),里面定义一个抽象方法:int add(int x,int y);
  • 定义一个测试类(AddableDemo),在测试类中提供两个方法:

一个方法是:useAddable(Addable a)

一个方法是主方法,在主方法中调用useAddable方法

06_Lambda表达式的省略模式

1.5、Lambda表达式的省略模式

省略的规则:

  • 参数类型可以省略。但是有多个参数的情况下,不能只省略一个。
  • 如果参数有且仅有一个,那么小括号可以省略。
  • 如果代码块的语句只有一条,可以省略大括号和分号,和return关键字。

07_Lambda表达式的注意事项

1.6、Lambda表达式的注意事项

注意事项:

  • 使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法。
  • 必须有上下文环境,才能推导出Lambda对应的接口。

根据局部变量的赋值得知Lambda对应的接口:Runnable r = () -> System.out.println("Lambda表达式");

根据调用方法的参数得知Lambda对应的接口:new Thread(() -> System.out.println("Lambda表达式")).start();

08_Lambda表达式和匿名内部类的区别

1.7、Lambda表达式和匿名内部类的区别

所需类型不同

  • 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类。
  • Lambda表达式:只能是接口。

使用限制不同

  • 如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类。
  • 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式。

实现原理不同

  • 匿名内部类:编译之后,产生一个单独的.class字节码文件。
  • Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成。

   

09_接口组成更新概述

1.1、接口组成更新概述

常量

  • public static final

抽象方法

  • public abstract
  • 默认方法(Java 8)
  • 静态方法(Java 8)
  • 私有方法(Java 9)

10_接口中默认方法

1.2、接口中默认方法

接口中默认方法的定义格式:

  • 格式:public default 返回值类型 方法名(参数列表) { }
  • 范例:public default void show3() { }

接口中默认方法的注意事项

  • 默认方法不是抽象方法,所以不强制被重写。但是可以被重写,重写的时候去掉default关键字。
  • public可以省略,default不能省略。

随着使用,接口满足不了需求,接口需要升级,接口需要添加新的功能“void show3();”,实现类MyInterfaceImplOne、MyInterfaceImplTwo需要重写所有抽象方法。麻烦!假如实现类有很多,接口中添加了一个方法,所有的实现类都要重写此方法;可能只有部分实现类需要重写此方法,所以这种设计不好。

接口的升级,可以这样做:新增接口MyInterfaceSon继承MyInterface实现“void show3();”,让实现类继承此接口(将来需要实现show3()方法的实现类实现MyInterfaceSon即可),不影响现有代码,解决接口的升级问题。弊端:每次添加新功能,都要新增子接口,并产生新的关系;实现show3()方法的实现类需要继承MyInterfaceSon接口;如果代码更新快,代码体系(代码继承、实现结构)就会变得非常庞大,不利于程序的维护。

更好的方式:默认方法(Java 8)

public变成灰色:public可以省略,default不能省略。

11_接口中静态方法

1.3、接口中静态方法

接口中静态方法的定义格式:

  • 格式:public static 返回值类型 方法名(参数列表) { }
  • 范例:public static void show() { }

接口中静态方法的注意事项

  • 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用。
  • public可以省略,static不能省略。

12_接口中私有方法

1.4、接口中私有方法

私有方法产生原因:

Java 9中新增了带方法体的私有方法,这其实在Java 8中就埋下了伏笔:Java 8允许在接口中定义带方法体的默认方法和静态方法。这样可能会引发一个问题:当两个默认方法或者静态方法中包含一段相同的代码实现时,程序必然考虑将这段实现代码抽取成一个共性方法,而这个共性方法是不需要让别人使用的,因此用私有给隐藏起来,这就是Java 9增加私有方法的必然性。

接口中私有方法的定义格式:

  • 格式1:private 返回值类型 方法名(参数列表) { }
  • 范例1:private void show() { }
  • 格式2:private static 返回值类型 方法名(参数列表) { }
  • 范例2:private static void method() { }

接口中私有方法的注意事项

  • 默认方法可以调用私有的静态方法和非静态方法。
  • 静态方法只能调用私有的静态方法。

method1()方法是静态方法,show()方法不是静态方法。静态方法不能调用非静态方法: 

13_体验方法引用

1.1、体验方法引用

方法引用的出现原因:

在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿参数做操作。

那么考虑一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再写重复逻辑呢?

答案肯定是没有必要。

那我们又是如何使用已经存在的方案的呢?

这就是我们要讲解的方法引用,我们是通过方法引用来使用已经存在的方案。

14_方法引用符

1.2、方法引用符

方法引用符:

  • :: 该符号为引用运算符,而它所在的表达式被称为方法引用。

回顾一下我们在体验方法引用中的代码:

  • Lambda表达式:usePrintable(s -> System.out.println(s));

分析:拿到参数s之后,通过Lambda表达式,传递给System.out.println方法去处理。

  • 方法引用:usePrintable(System.out::println);

分析:直接使用System.out中的println方法来取代Lambda,代码更加的简洁。

推导与省略:

  • 如果使用Lambda,那么根据“可推导就是可省略”的原则,无需指定参数类型,也无需指定的重载形式, 它们都将被自动推导。
  • 如果使用方法引用,也是同样可以根据上下文进行推导。
  • 方法引用是Lambda的孪生兄弟。

15_引用类方法

1.3、Lambda表达式支持的方法引用

常见的引用方式:

  • 引用类方法
  • 引用对象的实例方法
  • 引用类的构造方法
  • 引用构造器

1.4、引用类方法

引用类方法,其实就是引用类的静态方法。

  • 格式:类名::静态方法
  • 范例:Integer::parseInt

Integer类的方法:public static int parseInt(String s) 将此String转换为int类型数据

练习描述:

  • 定义一个接口(Converter),里面定义一个抽象方法。

int convert(String s);

  • 定义一个测试类(ConverterDemo),在测试类中提供两个方法。

一个方法是:useConverter(Converter c)

一个方法是主方法,在主方法中调用useConverter方法

使用说明:Lambda表达式被类方法替代的时候,它的形式参数全部传递给静态方法作为参数。

16_引用对象的实例方法

1.5、引用对象的实例方法

引用对象的实例方法,其实就引用类中的成员方法。

  • 格式:对象::成员方法
  • 范例:"HelloWorld"::toUpperCase

String类中的方法:public String toUpperCase() 将此String所有字符转换为大写。

练习描述:

  • 定义一个类(PrintString),里面定义一个方法。

public void printUpper(String s):把字符串参数变成大写的数据,然后在控制台输出。

  • 定义一个接口(Printer),里面定义一个抽象方法。

void printUpperCase(String s)

  • 定义一个测试类(PrinterDemo),在测试类中提供两个方法。

一个方法是:usePrinter(Printer p)

一个方法是主方法,在主方法中调用usePrinter方法。

使用说明:Lambda表达式被对象的实例方法替代的时候,它的形式参数全部传递给该方法作为参数。

17_引用类的实例方法

1.6、引用类的实例方法

引用类的实例方法,其实就是引用类中的成员方法。

  • 格式:类名::成员方法
  • 范例:String::substring

String类中的方法:public String substring(int beginIndex,int endIndex)

从beginIndex开始到endIndex结束,截取字符串。返回一个子串,子串的长度为endIndex-beginIndex。

练习描述:

  • 定义一个接口(MyString),里面定义一个抽象方法:

String mySubString(String s,int x,int y);

  • 定义一个测试类(MyStringDemo),在测试类中提供两个方法:

一个方法是:useMyString(MyString my)

一个方法是主方法,在主方法中调用useMyString方法

使用说明:Lambda表达式被类的实例方法替代的时候,第一个参数作为调用者,后面的参数全部传递给该方法作为参数。

18_引用构造器

1.7、引用构造器

引用构造器,其实就是引用构造方法。

  • 格式:类名::new
  • 范例:Student::new

练习描述:

  • 定义一个类(Student),里面有两个成员变量(name,age)

并提供无参构造方法和带参构造方法,以及成员变量对应的get和set方法。

  • 定义一个接口(StudentBuilder),里面定义一个抽象方法:

Student build(String name,int age);

  • 定义一个测试类(StudentDemo),在测试类中提供两个方法:

一个方法是:useStudentBuilder(StudentBuilder s)

一个方法是主方法,在主方法中调用useStudentBuilder方法

使用说明:Lambda表达式被构造器替代的时候,它的形式参数全部传递给构造器作为参数。

猜你喜欢

转载自blog.csdn.net/weixin_44949135/article/details/108229664