day22Lambda方法引用
1.Lambda表达式
1.1体验Lambda表达式【理解】
函数式编程·
案例需求
启动一个线程,在控制台输出一句话:多线程程序启动了实现方式一
- 实现步骤
- 定义一个类MyRunnable实现Runnable接口,重写run()方法
- 创建MyRunnable类的对象
- 创建Thread类的对象,把MyRunnable的对象作为构造参数传递
- 启动线程
- 实现步骤
实现方式二
- 匿名内部类的方式改进
实现方式三
- Lambda表达式的方式改进
代码演示
//方式一的线程类
public class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("多线程程序启动了");}
}
public class LambdaDemo {public static void main(String[] args) {//方式一 采用实现类来实现功能
// MyRunnable my = new MyRunnable();
// Thread t = new Thread(my);
// t.start();
//方式二 匿名内部类
// new Thread(new Runnable() {// @Override
// public void run() {// System.out.println("多线程程序启动了");
// }
// }).start();
//方式三 方法二的简洁写法new Thread( () -> {System.out.println("多线程程序启动了");} ).start();}
}
- 函数式编程思想概述
函数式思想则尽量忽略面向对象的复杂语法:
“强调做什么,而不是以什么形式去做”
而我们要学习的Lambda表达式就是函数式思想的体现
1.2Lambda表达式的标准格式【理解】
格式:
(形式参数) -> {代码块}- 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
- ->:由英文中画线和大于符号组成,固定写法。代表指向动作
- 代码块:是我们具体要做的事情,也就是以前我们写的方法体内容
组成Lambda表达式的三要素:
- 形式参数,箭头,代码块
1.3Lambda表达式练习1【应用】
Lambda表达式的使用前提
- 有一个接口
- 接口中有且仅有一个抽象方法
练习描述
无参无返回值抽象方法的练习操作步骤
- 定义一个接口(Eatable),里面定义一个抽象方法:void eat();
- 定义一个测试类(EatableDemo),在测试类中提供两个方法
- 一个方法是:useEatable(Eatable e)
- 一个方法是主方法,在主方法中调用useEatable方法
示例代码
//接口
public interface Eatable {void eat();
}
//实现类
public class EatableImpl implements Eatable {@Overridepublic void eat() {System.out.println("一天一苹果,医生远离我");}
}
//测试类
public class EatableDemo {public static void main(String[] args) {//在主方法中调用useEatable方法Eatable e = new EatableImpl(); //创建接口实例化对象useEatable(e);//匿名内部类useEatable(new Eatable() {@Overridepublic void eat() {System.out.println("一天一苹果,医生远离我");}});//Lambda表达式useEatable(() -> {System.out.println("一天一苹果,医生远离我");});}private static void useEatable(Eatable e) {e.eat();}
}
1.4Lambda表达式练习2【应用】
练习描述
有参无返回值抽象方法的练习操作步骤
- 定义一个接口(Flyable),里面定义一个抽象方法:void fly(String s);
- 定义一个测试类(FlyableDemo),在测试类中提供两个方法
- 一个方法是:useFlyable(Flyable f)
- 一个方法是主方法,在主方法中调用useFlyable方法
示例代码
public interface Flyable {void fly(String s);
}public class FlyableDemo {public static void main(String[] args) {//在主方法中调用useFlyable方法//匿名内部类useFlyable(new Flyable() {@Overridepublic void fly(String s) {System.out.println(s);System.out.println("飞机自驾游");}});System.out.println("-----------------");//LambdauseFlyable((String s) -> {System.out.println(s);System.out.println("飞机自驾游");});}private static void useFlyable(Flyable f) {f.fly("风和日丽,晴空万里");}
}
1.5Lambda表达式练习3【应用】
练习描述
有参有返回值抽象方法的练习操作步骤
- 定义一个接口(Addable),里面定义一个抽象方法:int add(int x,int y);
- 定义一个测试类(AddableDemo),在测试类中提供两个方法
- 一个方法是:useAddable(Addable a)
- 一个方法是主方法,在主方法中调用useAddable方法
示例代码
public interface Addable {int add(int x,int y); //返回int类型的结果
}public class AddableDemo {public static void main(String[] args) {//在主方法中调用useAddable方法useAddable((int x,int y) -> {return x + y;});}private static void useAddable(Addable a) {int sum = a.add(10, 20);System.out.println(sum);}
}
1.6Lambda表达式的省略模式【应用】
省略的规则
- 参数类型可以省略。但是有多个参数的情况下,不能只省略一个
- 如果参数有且仅有一个,那么小括号可以省略
- 如果代码块的语句只有一条,可以省略大括号和分号,和return关键字
代码演示
public interface Addable {int add(int x, int y);
}
public interface Flyable {void fly(String s);
}public class LambdaDemo {public static void main(String[] args) {// useAddable((int x,int y) -> {// return x + y;
// });//参数的类型可以省略useAddable((x, y) -> {return x + y;});// useFlyable((String s) -> {// System.out.println(s);
// });//如果参数有且仅有一个,那么小括号可以省略
// useFlyable(s -> {// System.out.println(s);
// });//如果代码块的语句只有一条,可以省略大括号和分号useFlyable(s -> System.out.println(s));//如果代码块的语句只有一条,可以省略大括号和分号,如果有return,return也要省略掉useAddable((x, y) -> x + y);}private static void useFlyable(Flyable f) {f.fly("风和日丽,晴空万里");}private static void useAddable(Addable a) {int sum = a.add(10, 20);System.out.println(sum);}
}
1.7Lambda表达式的注意事项【理解】
- 使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法
- 必须有上下文环境,才能推导出Lambda对应的接口
根据局部变量的赋值得知Lambda对应的接口
Runnable r = () -> System.out.println(“Lambda表达式”);根据调用方法的参数得知Lambda对应的接口
new Thread(() -> System.out.println(“Lambda表达式”)).start();
1.8Lambda表达式和匿名内部类的区别【理解】
所需类型不同
- 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
- Lambda表达式:只能是接口
使用限制不同
- 如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
- 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
实现原理不同
- 匿名内部类:编译之后,产生一个单独的.class字节码文件
- Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成
2.接口组成更新
2.1接口组成更新概述【理解】
常量(默认)
public static final抽象方法(默认)
public abstract默认方法(Java 8)
静态方法(Java 8)
私有方法(Java 9)
2.2接口中默认方法【应用】
格式
public default 返回值类型 方法名(参数列表) { }范例
public default void show3() {
}
- 注意事项
- 默认方法不是抽象方法,所以不强制被重写。但是可以被重写,重写的时候去掉default关键字
- public可以省略,default不能省略
2.3接口中静态方法【应用】
格式
public static 返回值类型 方法名(参数列表) { }范例
public static void show() {}
- 注意事项
- 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
- public可以省略,static不能省略
2.4接口中私有方法【应用】
私有方法产生原因
Java 9中新增了带方法体的私有方法,这其实在Java 8中就埋下了伏笔:Java 8允许在接口中定义带方法体的默认方法和静态方法。这样可能就会引发一个问题:当两个默认方法或者静态方法中包含一段相同的代码实现时,程序必然考虑将这段实现代码抽取成一个共性方法,而这个共性方法是不需要让别人使用的,因此用私有给隐藏起来,这就是Java 9增加私有方法的必然性定义格式
格式1
private 返回值类型 方法名(参数列表) { }范例1
private void show() { }
格式2
private static 返回值类型 方法名(参数列表) { }范例2
private static void method() { }
注意事项
- 默认方法可以调用私有的静态方法和非静态方法
- 静态方法只能调用私有的静态方法
3.方法引用
3.1体验方法引用【理解】
方法引用的出现原因
在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿参数做操作那么考虑一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再写重复逻辑呢?答案肯定是没有必要
那我们又是如何使用已经存在的方案的呢?
这就是我们要讲解的方法引用,我们是通过方法引用来使用已经存在的方案代码演示
public interface Printable {void printString(String s);
}public class PrintableDemo {public static void main(String[] args) {//在主方法中调用usePrintable方法
// usePrintable((String s) -> {// System.out.println(s);
// });//Lambda简化写法usePrintable(s -> System.out.println(s));//方法引用usePrintable(System.out::println);}private static void usePrintable(Printable p) {p.printString("爱生活爱Java");}
}
3.2方法引用符【理解】
方法引用符
:: 该符号为引用运算符,而它所在的表达式被称为方法引用推导与省略
- 如果使用Lambda,那么根据“可推导就是可省略”的原则,无需指定参数类型,也无需指定的重载形式,它们都将被自动推导
- 如果使用方法引用,也是同样可以根据上下文进行推导
- 方法引用是Lambda的孪生兄弟
3.3引用类方法【应用】
引用类方法,其实就是引用类的静态方法
格式
类名::静态方法范例
Integer::parseInt
Integer类的方法:public static int parseInt(String s) 将此String转换为int数据练习描述
- 定义一个接口(Converter),里面定义一个抽象方法 int convert(String s);
- 定义一个测试类(ConverterDemo),在测试类中提供两个方法
- 一个方法是:useConverter(Converter c)
- 一个方法是主方法,在主方法中调用useConverter方法
代码演示
public interface Converter {int convert(String s);
}
public class ConverterDemo {public static void main(String[] args) {//Lambda写法useConverter(s -> Integer.parseInt(s));//引用类方法useConverter(Integer::parseInt);}private static void useConverter(Converter c) {int number = c.convert("666");System.out.println(number);}
}
- 使用说明
Lambda表达式被类方法替代的时候,它的形式参数全部传递给静态方法作为参数
3.4引用对象的实例方法【应用】
引用对象的实例方法,其实就引用类中的成员方法
格式
对象::成员方法范例
“HelloWorld”::toUpperCase
String类中的方法:public String toUpperCase() 将此String所有字符转换为大写练习描述
定义一个类(PrintString),里面定义一个方法
public void printUpper(String s):把字符串参数变成大写的数据,然后在控制台输出定义一个接口(Printer),里面定义一个抽象方法
void printUpperCase(String s)定义一个测试类(PrinterDemo),在测试类中提供两个方法
- 一个方法是:usePrinter(Printer p)
- 一个方法是主方法,在主方法中调用usePrinter方法
代码演示
public class PrintString { //定义一个类//把字符串参数变成大写的数据,然后在控制台输出public void printUpper(String s) { //带参方法String result = s.toUpperCase(); //调用方法System.out.println(result);}
}
public interface Printer { //定义一个接口void printUpperCase(String s); //带参抽象方法
}public class PrinterDemo {public static void main(String[] args) {//Lambda简化写法usePrinter(s -> System.out.println(s.toUpperCase()));//引用对象的实例方法PrintString ps = new PrintString();usePrinter(ps::printUpper);
}private static void usePrinter(Printer p) { //使用接口方法p.printUpperCase("HelloWorld"); //接口对象调用方法
}
}
- 使用说明
Lambda表达式被对象的实例方法替代的时候,它的形式参数全部传递给该方法作为参数
3.5引用类的实例方法【应用】
引用类的实例方法,其实就是引用类中的成员方法
格式
类名::成员方法范例
String::substring
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方法
代码演示
public interface MyString {String mySubString(String s,int x,int y);
}
public class MyStringDemo {public static void main(String[] args) {//Lambda简化写法useMyString((s,x,y) -> s.substring(x,y));调用类的静态方法(参数)-> 实际调用方法//引用类的实例方法useMyString(String::substring);调用类的静态方法(对象:成员调用方法)}private static void useMyString(MyString my) {String s = my.mySubString("HelloWorld", 2, 5);System.out.println(s);}
}
- 使用说明
Lambda表达式被类的实例方法替代的时候
第一个参数作为调用者
后面的参数全部传递给该方法作为参数
3.6引用构造器【应用】
引用构造器,其实就是引用构造方法
格式
类名::new范例
Student::new练习描述
- 定义一个类(Student),里面有两个成员变量(name,age)
并提供无参构造方法和带参构造方法,以及成员变量对应的get和set方法 - 定义一个接口(StudentBuilder),里面定义一个抽象方法
Student build(String name,int age); - 定义一个测试类(StudentDemo),在测试类中提供两个方法
- 一个方法是:useStudentBuilder(StudentBuilder s)
- 一个方法是主方法,在主方法中调用useStudentBuilder方法
- 定义一个类(Student),里面有两个成员变量(name,age)
代码演示
public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}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 interface StudentBuilder {Student build(String name,int age);
}
public class StudentDemo {public static void main(String[] args) {//Lambda简化写法useStudentBuilder((name,age) -> new Student(name,age));//引用构造器useStudentBuilder(Student::new);}private static void useStudentBuilder(StudentBuilder sb) {Student s = sb.build("林青霞", 30);System.out.println(s.getName() + "," + s.getAge());}
}
- 使用说明
Lambda表达式被构造器替代的时候,它的形式参数全部传递给构造器作为参数
day22Lambda方法引用相关推荐
- Java 8 中的方法引用,轻松减少代码量,提升可读性!
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 1. 引言 Java8中最受广大开发中喜欢的变化之一是因为 ...
- 【Java8新特性】浅谈方法引用和构造器引用
写在前面 Java8中一个很牛逼的新特性就是方法引用和构造器引用,为什么说它很牛逼呢?往下看! 方法引用 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!这里需要注意的是:实现抽 ...
- java写方法用来调用_Java从入门到入土(79)lambda表达式和方法引用
lambda表达式是Java8引入的新功能.lambda表达式以字面量的形式把少量代码直接写在程序中,从而让 Java 编程更符合函数式风格(Java 实质上是面向对象语言.不过,引入lambda 表 ...
- 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)
作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...
- 你知道Java 8 的方法引用吗
1. 前言 Java中的方法引用,很多同学都见过但却叫不出名字甚至不太会用,在这篇文章中,我们将看到什么是方法引用以及如何使用它. 2. 方法引用的使用场景 我们先来看看方法引用的使用: new Ra ...
- 函数式接口、方法引用
概念 函数式接口在Java中是指:有且仅有一个抽象方法的接口. 函数式接口,即适用于函数式编程场景的接口.而Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用于Lambda使用的接 ...
- Java 8 - 06 Lambda 和方法引用实战
文章目录 Pre 第 1 步:传递代码 第 2 步:使用匿名类 第 3 步:使用 Lambda 表达式 第 4 步:使用方法引用 Pre 前几篇文章,我们已经学习了行为参数化.匿名类.Lambda表达 ...
- Java 8 - 05 方法引用
文章目录 Pre 方法引用 如何构建方法引用 指向静态方法的方法引用 指向任意类型实例方法的方法引用 指向现有对象的实例方法的方法引用 构造函数引用 自定义构造函数引用 Pre 先来看段代码 Comp ...
- Java8 之 lambda 表达式、方法引用、函数式接口、默认方式、静态方法
今天我来聊聊 Java8 的一些新的特性,确实 Java8 的新特性的出现,给开发者带来了非常大的便利,可能刚刚开始的时候会有点不习惯的这种写法,但是,当你真正的熟悉了之后,你一定会爱上这些新的特性的 ...
- java8新特性之lambda表达式(及方法引用与构造器引用)
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中).使用 Lambda 表达式可以使代码变的更加简洁紧凑. 一.语法 lambda 表达式的语法格式如下: (parameters) ...
最新文章
- mysql干货——数据库字符集和校对规则详解
- linux 添加最大串口数量方法
- Java使用iText生成word文件的完美解决方案(亲测可行)
- Swift 类的使用class
- wps分析工具库如何加载_怎么在wps表格里面加入“数据分析”工具啊?
- Quartus II 与ModelSim-Altera联合仿真PLL
- 卷积神经网络 第一周作业 Convolution+model+-+Application+-+v1
- 数学猜想验证步骤_10大仍未解开的数学难题
- 数字单片机的技术发展
- GridView的DataFormatString格式化字符串
- BOS v2.0后台管理系统 JQuery Easyui 相关知识讲解
- 牛顿迭代法(求平方根)
- html仿苹果桌面导航js css,JS+CSS仿苹果手机(Iphone)的滑动效果的焦点图
- oracle数据库统计信息的重要性
- seo整站优化到底该从哪些方面进行着手(干货分享)
- 烧写自定义ArduPilot到自定义的开发板
- 【微信小程序】创建项目
- HTML打造动漫人物,19个搭配很酷的卡通人物网站设计欣赏
- 把自己曾经写的一个客户间聊天的程序与大家分享(2)
- nginx1.14的安装
热门文章
- STM32下载程序时提示“active write protected stm32 device detected this could”
- 自然场景下评估面部连续的效价维和唤醒维
- ubuntu(18.04)中架设HiGlass docker镜像服务,已尝试mcool、bedpe、wig格式文件
- Android权限中文描述大全(转)
- LaTeX修改表格宽度的两个方案
- SMART200 PLC作为modbus TCP的客户端与其他设备实现数据的读写
- 【Python 1】
- 手机连电脑,无com口
- 2022年煤炭生产经营单位(安全生产管理人员)特种作业证考试题库及答案
- 用“创业与投资”类比来分析《西部世界》第一、二季的架构