2000字搞懂Java中Lambda+方法引用简化代码(开发代码量秒缩十倍)
1.代码块
- 代码块是类的5大成分之一(成员变量、构造器、方法、代码块、内部类)。
代码块分为两种:
1.1静态代码块
- 格式:static{}
- 特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只会执行一次。
- 作用:完成类的初始化,例如:对静态变量的初始化赋值。
1.2实例代码块
- 格式:{}
- 特点:每次创造对象时,执行实例代码块,并在构造器前执行。
- 作用:和构造器一样,都是用来完成对象的初始化的,例如:对实例变量进行初始化。
2.内部类
- 如果一个类定义在另一个类的内部,这个类就是内部类。
- 场景:当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类。
public class car{ //汽车类
//内部类
public class Engine{ //发动机类
}
}
我们在实际项目开发中,一般不会这么定义。
2.1成员内部类
就是类中的一个普通成员,类似于普通的成员变量、成员方法。
需要特别注意的是内部类创建对象的格式。
2.1.1成员内部类访问外部成员的特点(拓展)
- 成员内部类中可以直接访问外部类的静态成员,也可以直接访问外部类的实例成员
- 2.成员内部类的实例方法中,可以直接拿到当前寄生的外部类对象,外部类名.this
2.2静态内部类
- 有static修饰的内部类,属于外部类自己持有。
2.3局部内部类
- 局部内部类是定义在方法中、代码块中、构造器等执行体中。
这个是纯没有什么用。
2.4匿名内部类(重点)
2.4.1认识匿名内部类
- 是一种特殊的局部内部类
- 所谓匿名:指的是程序员不需要为这个类声明名字,默认有个隐藏的名字。
new 类或接口(参数值...){
类体(一般是方法重写)
}
//本质是一个Animal类的子类,并且会立即new一个对象(可以理解为猫类或者狗类)
new Animal(){
@Override
public voidcry(){
}
};
- 特点:匿名内部类本质就是一个子类,并会立即创建出一个子类对象。
- 作用:用于更方便的创建一个子类对象。
匿名内部类实际是有名字的 外部内部类名$编号.class
2.4.2常见使用形式
- 通常作为一个参数对象传输给方法。
- 需求:学生、老师要求参加游泳比赛。
我们可以进一步简化Test2_1,直接把匿名内部类作为方法参数传进去。
2.4.3应用场景
- 调用别人提供的方法实现开发需求时,这个方法正好可以让我们传输一个匿名内部类对象给其使用。
- 开发中一般不是我们要主动去写匿名内部类,而是使用别人的功能时,别人可以让我们写一个匿名内部类,我们才会写。
匿名内部类也可以简化成一行。
所以匿名内部类可以起到简化代码的作用。
2.4.4案例:使用comparator接口的匿名内部类实现对数组进行排序
我们需要先声明一个学生类
我们先准备好数据
然后我们现在假设需要对年龄进行升序排序,如果我们自己写,可能就需要涉及到比如说冒泡排序,快排种种算法,我们现在可以直接用sun公司写好的API进行排序。
最后我们看一下完整的代码和流程。
3.函数式编程
3.1Lambda
3.1.1函数式编程的介绍
- 此函数类似于数学中的函数(强调做什么),只需要输入的数据一致,返回的结果也是一致的。
数学中的函数实例:2x+1
Java中的函数(Lambda表达式):(x)->2x+1
切记,Java中的函数和C语言中的方法是有区别的,这是两个概念,Java中的函数是Lambda表达式。
函数式编程解决了什么问题?
- JDK8开始新增的一种语法形式,它表示函数。
- 使用Lambda函数替代了某些匿名类对象,从而让代码更简洁,可读性更好。
//Lambda格式
(被重写方法的形参列表)->{
被重写方法的方法体代码
}
- Lambda并不能简化全部的匿名内部类,Lambda只能简化函数式接口的匿名内部类。
什么是函数式接口?
- 有且仅有一个抽象方法的接口。
- Lambda的这种推断也叫上下文推断。
- 注意:将来我们见到的大部分函数式接口,上面都可能会有一个@FunctionalInterface的注解,该注解用于约束当前接口必须是函数式接口,一旦内部抽象函数数量不为1都会报错,可以保证程序的安全性。
3.1.2使用Lambda简化comparator接口的匿名内部类
3.1.3Lambda表达式的省略规则
- 作用:用于进一步简化Lambda表达式的写法。
具体规则
- 参数类型可以全部省略不写
- 如果只有一个参数,参数类型省略的同时”()“也可以省略,但多个参数不能省略”()“
- 如果Lambda表达式中只有一行代码,大括号可以不写,同时要省略分号”;“如果这行代码是return语句,也必须去掉return。
3.2函数式编程-方法引用
3.2.1静态方法的引用
使用格式
类名::静态方法
使用场景
- 如果某个Lambda表达式里只是调用一个静态方法,并且“→”前后参数的形式一致,就可以使用静态方法引用。
3.2.2实例方法的引用
使用格式
对象名::实例方法
使用场景
- 如果某个Lambda表达式里只是通过对象名称调用一个实例方法,并且“→”前后参数的形式一致,就可以使用实例方法引用。
但其实这个是比较变态的写法,一般用不太上。
3.2.3特定类型方法的引用
使用格式
特定类的名称::方法
使用场景
- 如果某个Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参,此时就可以使用特定类型的方法引用。
我们可以看到这个sort是按照编号排序,所以a在A后面,中文编号更大所以在后面。
但是我们要求忽略首字母大小进行升序排序。
根据sun公司写好的方法,我们可以很便捷的忽略大小写进行排序,那么现在的问题就回归正题,怎么用方法引用对这段代码进行简化?
3.2.4构造器引用
使用格式
类名::new
使用场景
- 如果某个Lambda表达式里只是在创建对象,并且“→”前后参数情况一致,就可以使用构造器引用。
这是我们人为创造的一个可以使用构造器引用的场景。
接下来就是开始简化代码。
感谢观看。