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