- 视频+资料【链接:https://pan.baidu.com/s/1MdFNUADVSFf-lVw3SJRvtg 提取码:zjxs】
- Java基础--学习笔记(零起点打开java世界的大门)--博客汇总表
目 录
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表达式被构造器替代的时候,它的形式参数全部传递给构造器作为参数。