方法引用
什么是方法引用
- 方法引用是Lambda表达式的一种特殊形式。
- 方法引用提供了一种更简洁的方式来为Lambda参数指定现有的方法或构造器。
- 方法引用需要一个与现有方法声明兼容的函数式接口。
- 方法引用语法为:Classname::methodName
使用方法引用
举个例子就懂了,使用已经存在的方法去替换我们的Lambda表达式。
一般函数表达式写法:
csharp
public class MyClass{
public static void main(String[] args) {
addMethod(5,6,(a,b) -> a+b);
}
public static int addMethod(int a, int b, MyFunction myFunction){
return myFunction.add(a,b);
}
}
@FunctionalInterface
interface MyFunction {
int add(int a, int b);
}
使用方法引用:
csharp
public class MyClass{
public static void main(String[] args) {
addMethod(5,6, Integer::sum);
}
public static int addMethod(int a, int b, MyFunction myFunction){
return myFunction.add(a,b);
}
}
@FunctionalInterface
interface MyFunction {
int add(int a, int b);
}
可以看到: 我的函数式表达式(a,b) -> return a+b
替换为Integer::sum
, 把代码拷贝下来跑一跑。
为什么可以这样替换呢?
因为它们的逻辑与方法相同(Integer的sum函数是求和,而我的函数式接口也是求和,方法的逻辑相同,参数列表也相同),就可以直接替换。
Integer类的sum方法:
arduino
public static int sum(int a, int b) {
return a + b;
}
是不是和我的add方法一模一样呢。
方法引用的好处
那替换有什么好处呢?
- 更简洁 - 不需要具体参数列表
- 更易读 - 方法名直接说明功能
- 代码复用 - 使用已经存在的函数,不用自己再去构造,效率肯定比自己写更高
方法引用的主要形式包括:
- 对象::实例方法
- 类::静态方法
- 类::实例方法
- 类构造器::new
- 数组类型[]::new
下面对四种形式进行举例子
对象::实例方法
创建类的实例,再去使用它的方法
typescript
public class MyClass{
public static void main(String[] args) {
MyClass myClass = new MyClass();
myClass.test();
}
public void test(){
// 创建实例
Cat cat = new Cat();
// 定义消费者接口
Consumer<String> cs1 = (s) -> System.out.println("cat eat " + s);
Consumer<String> cs2 = cat::eat;
// 调用方法
cs1.accept("fish");
cs2.accept("fish");
}
}
class Cat{
public void eat(String s){
System.out.println("cat eat " + s);
}
}
类::静态方法
直接使用类的静态方法
typescript
public class MyClass{
public static void main(String[] args) {
MyClass myClass = new MyClass();
myClass.test();
}
public void test(){
// 定义消费者接口
Consumer<String> cs1 = (s) -> System.out.println("cat eat " + s);
Consumer<String> cs2 = Cat::eat;
// 调用方法
cs1.accept("fish");
cs2.accept("fish");
}
}
class Cat{
public static void eat(String s){
System.out.println("cat eat " + s);
}
}
类::实例方法
ini
// 方法引用-类名::实例方法名
BiFunction<String, String, Boolean> fun1 = (str1, str2) -> str1.equals(str2);
BiFunction<String, String, Boolean> fun2 = String::equals;
Boolean result2 = fun2.apply("hello", "world");
System.out.println(result2);
这个只能使用JavaJDK已经编写好的类的函数,自己编写的函数需要设为static。
类构造器::new
typescript
public class Solution {
public static void main(String[] args) {
// 使用lambda表达式
Function<String, Cat> f1 = (s)-> new Cat(s);
Cat c1 = f1.apply("小白");
System.out.println(c1.getName());
// 使用方法引用
Function<String, Cat> f2 = Cat::new;
Cat c2 = f2.apply("小黑");
System.out.println(c2.getName());
}
}
class Cat{
private String name;
Cat(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
注意: 使用的时候传入的参数列表需要和构造函数相匹配。比如我里面用的Fuction
接口,刚刚好就是我们Cat
类的对应形式,构造函数返回值为它的类对象。
如果要匹配多个参数怎么办???
答案是我们自己定义函数接口呗,比如定义一个接收三个参数的:
scss
@FunctionalInterface
interface CatFactory<T,V,R>{
Cat getCat(T a1, V a2, R a3);
}
数组类型[]::new
typescript
public class Solution {
public static void main(String[] args) {
ArrayFactory<String> af = String[]::new;
String[] strings = af.create(5);
}
}
@FunctionalInterface
interface ArrayFactory<T> {
T[] create(int size);
}