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
。具体示例代码如下。
@FunctionalInterface
public interface TestMethodRefInterface1 {
int onlyMethod(String a, String b);
}
@FunctionalInterface
public interface TestMethodRefInterface2 {
int onlyMethod(TestMethodRefBean a, String b);
}
@FunctionalInterface
public interface TestMethodRefInterface3 {
int onlyMethod(TestMethodRefBean a, String b, int c);
}
@FunctionalInterface
public interface TestMethodRefInterface4 {
int onlyMethod(TestMethodRefBean a);
}
public class TestMethodRefBean {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int recvStrRetInt(String str) {
return 0;
}
public int recvStrIntRetInt(String str, int i) {
return 0;
}
}
import org.springframework.stereotype.Service;
@Service
public class TestMethodRefReceiverService {
private TestMethodRefBean bean = new TestMethodRefBean();
public void methodParamIf1(TestMethodRefInterface1 x) {
// call the implementation method
x.onlyMethod("foo", "bar");
}
public void methodParamIf2(TestMethodRefInterface2 x) {
// call the implementation method
x.onlyMethod(bean, "foo");
}
public void methodParamIf3(TestMethodRefInterface3 x) {
// call the implementation method
x.onlyMethod(bean, "foo", 0);
}
public void methodParamIf4(TestMethodRefInterface4 x) {
// call the implementation method
x.onlyMethod(bean);
}
}
import org.springframework.stereotype.Service;
@Service
public class TestMethodRefProviderService {
public static int staticMethod(String str, String str2) {
return 0;
}
public static int staticMethod2(TestMethodRefBean pojo, String str) {
return 0;
}
public int instanceMethod(String str, String str2) {
return 0;
}
public int instanceMethod2(TestMethodRefBean pojo, String str) {
return 0;
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class TestMethodRefService {
@Autowired
private TestMethodRefReceiverService receiverService;
@Autowired
private TestMethodRefProviderService providerService;
public void runner() {
receiverService.methodParamIf1((a, b) -> 0);
receiverService.methodParamIf1(TestMethodRefProviderService::staticMethod);
receiverService.methodParamIf1(providerService::instanceMethod);
receiverService.methodParamIf1(String::compareTo);
receiverService.methodParamIf1(String::indexOf);
receiverService.methodParamIf2((a, b) -> 0);
receiverService.methodParamIf2(TestMethodRefProviderService::staticMethod2);
receiverService.methodParamIf2(providerService::instanceMethod2);
receiverService.methodParamIf2(TestMethodRefBean::recvStrRetInt);
receiverService.methodParamIf3(TestMethodRefBean::recvStrIntRetInt);
receiverService.methodParamIf4(TestMethodRefBean::getAge);
}
}
end