1.1 目标
了解Lambda的冗余场景
掌握方法引用的格式
了解常见的方法引用方式
1.2 Lambda的冗余场景
使用Lambda表达式求一个数组的和
package com.itheima.demo04methodref;
import java.util.function.Consumer;
public class Demo01MethodRefIntro {
// 求一个数组的和
public static void getMax(int[] arr) {
int sum = 0;
for (int n : arr) {
sum += n;
}
System.out.println(sum);
}
public static void main(String[] args) {
// 使用Lambda表达式求一个数组的和
printMax((int[] arr) -> {
getMax(arr);
});
// 使用方法引用
// 让这个指定的方法去重写接口的抽象方法,到时候调用接口的抽象方法就是调用传递过去的这个方法
printMax(Demo01MethodRefIntro::getMax);
}
public static void printMax(Consumer<int[]> consumer) {
int[] arr = {11, 22, 33, 44, 55};
consumer.accept(arr);
}
}
1.3 体验方法引用简化Lambda
如果我们在Lambda中所指定的功能,已经有其他方法存在相同方案,那是否还有必要再写重复逻辑?可以直接“引
用”过去就好了:
请注意其中的双冒号 :: 写法,这被称为“方法引用”,是一种新的语法。
1.4 方法引用的格式
符号表示 : ::
符号说明 : 双冒号为方法引用运算符,而它所在的表达式被称为方法引用。
应用场景 : 如果Lambda所要实现的方案 , 已经有其他方法存在相同方案,那么则可以使用方法引用。
1.5 常见引用方式
方法引用在JDK 8中使用方式相当灵活,有以下几种形式:
1. instanceName::methodName 对象::方法名
2. ClassName::staticMethodName 类名::静态方法
3. ClassName::methodName 类名::普通方法
4. ClassName::new 类名::new 调用的构造器
5. TypeName[]::new String[]::new 调用数组的构造器
1.6 小结
首先了解Lambda表达式的冗余情况,体验了方法引用,了解常见的方法引用方式
1.7 对象名::引用成员方法
这是最常见的一种用法,与上例相同。如果一个类中已经存在了一个成员方法,则可以通过对象名引用成员方法,代
码为:
// 对象::实例方法
@Test
public void test01() {
Date now = new Date();
Supplier<Long> su1 = () -> {
return now.getTime();
};
// 使用方法引用
Supplier<Long> su1 = now::getTime;
Long aLong = su1.get();
System.out.println("aLong = " + aLong);
// 注意:方法引用有两个注意事项
// 1.被引用的方法,参数要和接口中抽象方法的参数一样
// 2.当接口抽象方法有返回值时,被引用的方法也必须有返回值
// Supplier<Long> su3 = now::setTime;
// su3.get();
// Supplier<Long> su4 = now::setDate;
// su4.get();
}
方法引用的注意事项
1. 被引用的方法,参数要和接口中抽象方法的参数一样
2. 当接口抽象方法有返回值时,被引用的方法也必须有返回值
1.8 类名::引用静态方法
由于在 java.lang.System 类中已经存在了静态方法 currentTimeMillis ,所以当我们需要通过Lambda来调用该
方法时,可以使用方法引用 , 写法是:
// 类名::静态方法
@Test
public void test02() {
Supplier<Long> su = () -> {
return System.currentTimeMillis();
};
Supplier<Long> su = System::currentTimeMillis;
Long time = su.get();
System.out.println("time = " + time);
}
1.9 类名::引用实例方法
Java面向对象中,类名只能调用静态方法,类名引用实例方法是有前提的,实际上是拿第一个参数作为方法的调用
者。
// 类名::实例方法
@Test
public void test03() {
Function<String, Integer> f1 = (String str) -> {
return str.length();
};
// 类名::实例方法(注意:类名::类名::实例方法实际上会将第一个参数作为方法的调用者)
Function<String, Integer> f1 = String::length;
int length = f1.apply("hello");
System.out.println("length = " + length);
// BiFunction<String, Integer, String> f2 = String::substring;
// 相当于这样的Lambda
BiFunction<String, Integer, String> f2 = (String str, Integer index) -> {
return str.substring(index);
};
String str2 = f2.apply("helloworld", 3);
System.out.println("str2 = " + str2); // loworld
}
1.10 类名::new引用构造器
由于构造器的名称与类名完全一样。所以构造器引用使用 类名称::new 的格式表示。首先是一个简单的 Person 类:
要使用这个函数式接口,可以通过方法引用传递:
// 类名::new引用类的构造器
@Test
public void test04() {
Supplier<Person> su1 = () -> {
return new Person();
};
Supplier<Person> su1 = Person::new;
Person person = su1.get();
System.out.println("person = " + person);
BiFunction<String, Integer, Person> bif = (String name, Integer age) -> {
return new Person(name, age);
};
BiFunction<String, Integer, Person> bif = Person::new;
Person p2 = bif.apply("凤姐", 18);
System.out.println("p2 = " + p2);
}
1.11 小结
方法引用是对Lambda表达式符合特定情况下的一种缩写,它使得我们的Lambda表达式更加的精简,也可以理解为
Lambda表达式的缩写形式 , 不过要注意的是方法引用只能”引用”已经存在的方法
package com.itheima.demo04methodref;
import org.junit.Test;
import java.util.Arrays;
import java.util.Date;
import java.util.function.*;
/*
方法引用的注意事项:
1.被引用的方法,参数要和接口中抽象方法的参数一样
2.当接口抽象方法有返回值时,被引用的方法也必须有返回值
*/
public class Demo02 {
// 类型[]::new
@Test
public void test05() {
Function<Integer, int[]> f1 = (Integer length) -> {
return new int[length];
};
Function<Integer, int[]> f1 = int[]::new;
int[] arr1 = f1.apply(10);
System.out.println(Arrays.toString(arr1));
}
// 类名::new引用类的构造器
@Test
public void test04() {
Supplier<Person> su1 = () -> {
return new Person();
};
Supplier<Person> su1 = Person::new;
Person person = su1.get();
System.out.println("person = " + person);
BiFunction<String, Integer, Person> bif = (String name, Integer age) -> {
return new Person(name, age);
};
BiFunction<String, Integer, Person> bif = Person::new;
Person p2 = bif.apply("凤姐", 18);
System.out.println("p2 = " + p2);
}
// 类名::实例方法
@Test
public void test03() {
Function<String, Integer> f1 = (String str) -> {
return str.length();
};
// 类名::实例方法(注意:类名::类名::实例方法实际上会将第一个参数作为方法的调用者)
Function<String, Integer> f1 = String::length;
int length = f1.apply("hello");
System.out.println("length = " + length);
// BiFunction<String, Integer, String> f2 = String::substring;
// 相当于这样的Lambda
BiFunction<String, Integer, String> f2 = (String str, Integer index) -> {
return str.substring(index);
};
String str2 = f2.apply("helloworld", 3);
System.out.println("str2 = " + str2); // loworld
}
// 类名::静态方法
@Test
public void test02() {
/*Supplier<Long> su = () -> {
return System.currentTimeMillis();
};*/
Supplier<Long> su = System::currentTimeMillis;
Long time = su.get();
System.out.println("time = " + time);
}
// 对象::实例方法
@Test
public void test01() {
Date now = new Date();
/*Supplier<Long> su1 = () -> {
return now.getTime();
};*/
// 使用方法引用
Supplier<Long> su1 = now::getTime;
Long aLong = su1.get();
System.out.println("aLong = " + aLong);
// 注意:方法引用有两个注意事项
// 1.被引用的方法,参数要和接口中抽象方法的参数一样
// 2.当接口抽象方法有返回值时,被引用的方法也必须有返回值
// Supplier<Long> su3 = now::setTime;
// su3.get();
// Supplier<Long> su4 = now::setDate;
// su4.get();
}
}