Java 中的 method reference 可以理解为 lambda 表达式的简略写法。阅读此篇需要有 lambda 表达式基础。
首先引用Oracle官网的The Java™ Tutorials的表述:
You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, it’s often clearer to refer to the existing method by name. Method references enable you to do this…
形式上method references分为四种:
| Kind | Example |
|---|---|
| Reference to a static method | ContainingClass::staticMethodName |
| Reference to an instance method of a particular object | containingObject::instanceMethodName |
| Reference to an instance method of an arbitrary object of a particular type | ContainingType::methodName |
| Reference to a constructor | ClassName::new |
其中第三条相对较难理解,举例如下:
例如,某函数式接口的抽象方法的方法签名是int name(ClassA a, ClassB b, ClassC c),而它的实现是ClassA类的实例方法int xxx(ClassB bbb, ClassC ccc),那么用method reference写法可以写成:ClassA::xxx。具体示例代码如下。
- 接口1~6,接收参数类型各不同
public interface MyFunctionalInterface1 {
int onlyMethod(String a, String b);
}
public interface MyFunctionalInterface2 {
int onlyMethod(MyPojo a, String b);
}
public interface MyFunctionalInterface3 {
int onlyMethod(MyPojo a, String b, int c);
}
public interface MyFunctionalInterface4 {
int onlyMethod(MyPojo a);
}
public interface MyFunctionalInterface5 {
void onlyMethod(String a, String b);
}
public interface MyFunctionalInterface6<R> {
R onlyMethod();
}
- 入参类
import static com.navinfo.platform.methodref.Logger.print;
public class MyPojo {
public int getAge() {
print("MyPojo.getAge", "int()");
return 0;
}
public int getChar(String str) {
print("MyPojo.getChar", "int(String)");
return 0;
}
public int getCharAt(String str, int i) {
print("MyPojo.getCharAt", "int(String,int)");
return 0;
}
}
- 打印日志工具类
public class Logger {
public static void print(String method, String message) {
System.out.printf("[%-16s] %s\n", method, message);
}
}
- 实现方法提供者
import static com.navinfo.platform.methodref.Logger.print;
public class MethodProviderService {
public static int staticMethod1(String str, String str2) {
print("staticMethod1", "int(String,String)");
return 0;
}
public static int staticMethod2(MyPojo pojo, String str) {
print("staticMethod2", "int(MyPojo,String)");
return 0;
}
public int instanceMethod1(String str, String str2) {
print("instanceMethod1", "int(String,String)");
return 0;
}
public int instanceMethod2(MyPojo pojo, String str) {
print("instanceMethod2", "int(MyPojo,String)");
return 0;
}
public int instanceMethod3(MyPojo pojo, String str, int i) {
print("instanceMethod3", "int(MyPojo,String,int)");
return 0;
}
public void instanceMethod4(String str, String str2) {
print("instanceMethod4", "void(String,String)");
}
}
- 测试主类
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
import static com.navinfo.platform.methodref.Logger.print;
public class TestMethodRefMain {
private MethodProviderService providerService = new MethodProviderService();
private MyPojo somePojo = new MyPojo();
public static void main(String[] args) {
new TestMethodRefMain().run();
}
private void run() {
consumeIf1(MethodProviderService::staticMethod1);
consumeIf1(providerService::instanceMethod1);
consumeIf1((s1, s2) -> s1.indexOf(s2));
consumeIf1(String::indexOf);
consumeIf2(MethodProviderService::staticMethod2);
consumeIf2(providerService::instanceMethod2);
consumeIf2((o, s) -> o.getChar(s));
consumeIf2(MyPojo::getChar);
consumeIf3(providerService::instanceMethod3);
consumeIf3((o, s, i) -> o.getCharAt(s, i));
consumeIf3(MyPojo::getCharAt);
consumeIf4(o -> o.getAge());
consumeIf4(MyPojo::getAge);
consumeIf5(providerService::instanceMethod4);
consumeIf5(providerService::instanceMethod1);
consumeIf5((s1, s2) -> new Object());
consumeIf5(Objects::<String>requireNonNull);
consumeIf5(String::startsWith);
consumeIf5(Arrays::asList);
consumeIf6(ArrayList<String>::new);
}
private void consumeIf1(MyFunctionalInterface1 x) {
print("consumeIf1", "接收 MyFunctionalInterface1 入参,方法签名 int(String,String)");
x.onlyMethod("foo", "bar");
}
private void consumeIf2(MyFunctionalInterface2 x) {
print("consumeIf2", "接收 MyFunctionalInterface2 入参,方法签名 int(MyPojo,String)");
x.onlyMethod(somePojo, "foo");
}
private void consumeIf3(MyFunctionalInterface3 x) {
print("consumeIf3", "接收 MyFunctionalInterface3 入参,方法签名 int(MyPojo,String,int)");
x.onlyMethod(somePojo, "foo", 0);
}
private void consumeIf4(MyFunctionalInterface4 x) {
print("consumeIf4", "接收 MyFunctionalInterface4 入参,方法签名 int(MyPojo)");
x.onlyMethod(somePojo);
}
private void consumeIf5(MyFunctionalInterface5 x) {
print("consumeIf5", "接收 MyFunctionalInterface5 入参,方法签名 void(String,String)");
x.onlyMethod("foo", "bar");
}
private void consumeIf6(MyFunctionalInterface6 x) {
print("consumeIf6", "接收 MyFunctionalInterface6 入参,方法签名 <R> R()");
x.onlyMethod();
}
}
- 打印结果
[consumeIf1 ] 接收 MyFunctionalInterface1 入参,方法签名 int(String,String)
[staticMethod1 ] int(String,String)
[consumeIf1 ] 接收 MyFunctionalInterface1 入参,方法签名 int(String,String)
[instanceMethod1 ] int(String,String)
[consumeIf1 ] 接收 MyFunctionalInterface1 入参,方法签名 int(String,String)
[consumeIf1 ] 接收 MyFunctionalInterface1 入参,方法签名 int(String,String)
[consumeIf2 ] 接收 MyFunctionalInterface2 入参,方法签名 int(MyPojo,String)
[staticMethod2 ] int(MyPojo,String)
[consumeIf2 ] 接收 MyFunctionalInterface2 入参,方法签名 int(MyPojo,String)
[instanceMethod2 ] int(MyPojo,String)
[consumeIf2 ] 接收 MyFunctionalInterface2 入参,方法签名 int(MyPojo,String)
[MyPojo.getChar ] int(String)
[consumeIf2 ] 接收 MyFunctionalInterface2 入参,方法签名 int(MyPojo,String)
[MyPojo.getChar ] int(String)
[consumeIf3 ] 接收 MyFunctionalInterface3 入参,方法签名 int(MyPojo,String,int)
[instanceMethod3 ] int(MyPojo,String,int)
[consumeIf3 ] 接收 MyFunctionalInterface3 入参,方法签名 int(MyPojo,String,int)
[MyPojo.getCharAt] int(String,int)
[consumeIf3 ] 接收 MyFunctionalInterface3 入参,方法签名 int(MyPojo,String,int)
[MyPojo.getCharAt] int(String,int)
[consumeIf4 ] 接收 MyFunctionalInterface4 入参,方法签名 int(MyPojo)
[MyPojo.getAge ] int()
[consumeIf4 ] 接收 MyFunctionalInterface4 入参,方法签名 int(MyPojo)
[MyPojo.getAge ] int()
[consumeIf5 ] 接收 MyFunctionalInterface5 入参,方法签名 void(String,String)
[instanceMethod4 ] void(String,String)
[consumeIf5 ] 接收 MyFunctionalInterface5 入参,方法签名 void(String,String)
[instanceMethod1 ] int(String,String)
[consumeIf5 ] 接收 MyFunctionalInterface5 入参,方法签名 void(String,String)
[consumeIf5 ] 接收 MyFunctionalInterface5 入参,方法签名 void(String,String)
[consumeIf5 ] 接收 MyFunctionalInterface5 入参,方法签名 void(String,String)
[consumeIf5 ] 接收 MyFunctionalInterface5 入参,方法签名 void(String,String)
[consumeIf6 ] 接收 MyFunctionalInterface6 入参,方法签名 <R> R()
end
本文深入解析Java中的方法引用,一种简化lambda表达式的语法糖。通过详细的示例代码,阐述了方法引用的四种形式:静态方法引用、特定实例方法引用、任意实例方法引用及构造器引用。文章展示了如何在不同的函数式接口中应用这些方法引用,提高代码的可读性和简洁性。
2万+

被折叠的 条评论
为什么被折叠?



