一、方法引用
1. 作用
- 通过直接引用方法名的方式来重写函数式接口中的抽象方法
2. 使用前提
- 如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么可以通过双冒号来引用该方法作为Lambda的替代者
- 双冒号"::"为引用运算符
3. 注意事项
- Lambda中传递的参数,一定是方法引用中的那个方法可以接收的数据类型,否则就会抛出异常
二、通过对象名来引用成员方法
1. 使用前提
2. 代码格式
对象名::成员方法名
3. 代码演示
@FunctionalInterface
public interface Printable {
void print(String s);
}
/**
* 使字符串大写并打印
* */
public class MethodRerObject {
public void printUpperCaseString(String str){
System.out.println(str.toUpperCase());
}
}
public class DemoObjectMethodReference {
// 静态方法:实现接口中的抽象方法
public static void printString(Printable p){
p.print("hello world");
}
public static void main(String[] args) {
MethodRerObject obj = new MethodRerObject();
// Lambda方式:通过Lambda表达式重写抽象方法的方法体,即调用成员方法
printString((s)->{
obj.printUpperCaseString(s);
});
// 优化方式:通过对象名引用成员方法
printString(obj::printUpperCaseString);
}
}
三、通过类名引用静态成员方法
1. 使用前提
2. 代码格式
类名::静态方法名
3. 代码演示
@FunctionalInterface
public interface Calcable {
// 定义一个抽象方法,传递一个整数,对整数进行绝对值计算并返回
int calAbs(int number);
}
public class DemoStaticMethodReference {
// 定义一个方法,方法的参数是要计算的绝对值整数和函数式接口
public static int method(int number, Calcable c){
return c.calAbs(number);
}
public static void main(String[] args) {
// Lambda方式:通过传递lambda表达式重写抽象方法的方法体,返回计算后的结果
int number = method(-10, (n)->{
return Math.abs(n);
});
System.out.println(number);
/**
* 通过方法引用优化Lambda表达式
* Math是类名
* abs()方法为静态成员方法
* */
int number2 = method(-10, Math::abs);
System.out.println(number2);
}
}
四、通过super引用成员方法
1. 代码格式
super::成员方法名
2. 代码演示
@FunctionalInterface
public interface Greetable {
void Greet();
}
/**
* 定义父类
* */
public class Human {
public void sayHello() {
System.out.println("你好,我是Human");
}
}
/**
* 定义子类,并通过方法引用调用父类的成员方法
* */
public class Man extends Human{
// 重写父类方法
@Override
public void sayHello() {
System.out.println("你好,我是man");
}
// 定义一个方法传递Greetable接口
public void method(Greetable g){
g.greet();
}
public void show(){
// Lambda方式:调用method方法,方法的参数是函数式接口
method(()->{
// 调用父类的sayHello方法
super.sayHello();
});
// 方法引用:由于存在子父类的关系,所以可以直接通过super引用方法
method(super::sayHello);
}
public static void main(String[] args) {
new Man().show();
}
}
五、通过this引用本类的成员方法
1. 代码格式
this::成员方法名
2. 代码演示
@FunctionalInterface
public interface Greetable {
void Greet();
}
public class Man{
// 定义一个成员方法
public void sayHello() {
System.out.println("你好,我是man");
}
// 定义一个方法传递Greetable接口
public void method(Greetable g){
g.greet();
}
public void show(){
// Lambda方式:调用method方法,方法的参数是函数式接口
method(()->{
// 调用本类中的sayHello方法
this.sayHello();
});
// 方法引用
method(this::sayHello);
}
public static void main(String[] args) {
new Man().show();
}
}
六、类的构造方法引用
1. 作用
2. 代码格式
类名::new
3. 代码演示
public class Person {
private String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@FunctionalInterface
public interface PersonBuilder {
// 定义一个方法,根据传递的姓名,创建对象
Person builderPerson(String name);
}
- 定义一个类,分别通过Lambda方式和方法引用方式创建对象
public class Demo {
// 定义一个方法,参数传递"姓名"和 "PersonBuilder接口",方法中通过姓名来创建Person对象
public static void printPersonName(String name, PersonBuilder p) {
Person person = p.builderPerson(name);
System.out.println(person.getName());
}
public static void main(String[] args) {
// Lambda方式:根据传递的姓名来构造Person对象
printPersonName("古力娜扎", (name)->{
return new Person(name);
});
// 方法引用
printPersonName("迪丽热巴",Person::new);
}
}
七、数组的构造器引用
1. 作用
2. 代码格式
int[]::new
3. 代码演示
/**
* 定义一个创建数组的函数式接口
* */
@FunctionalInterface
public interface ArrayBuilder {
// 定义一个创建int类型数组的方法,参数传递数组的长度,最后返回创建好的int类型的数组
int[] builderArray(int length);
}
- 定义一个类,分别通过lambda方式和方法引用来创建数组
public class Demo {
/**
* 定义一个方法
* 方法的参数传递创建数组的长度和ArrayBuilder接口
* 方法内部根据传递的长度使用ArrayBuilder中的方法并返回创建后的数组
* */
public static int[] createArray(int length, ArrayBuilder ab) {
return ab.builderArray(length);
}
public static void main(String[] args) {
// 使用Lambda方式传参创建数组
int[] array1 = createArray(10, (length)->{
return new int[length];
});
System.out.println(array1.length);
// 使用方法引用创建数组
int[] array2 = createArray(11, int[]::new);
System.out.println(array2.length);
}
}