方法引用其实就是方法调用,符号是两个冒号::来表示,左边是对象或类,右边是方法。它其实就是lambda表达式的进一步简化。如果不使用lambda表达式,那么也就没必要用方法引用了。啥是lambda,参见jdk1.8新特性之lambda表达式。看实际例子:
先看函数式接口:
@FunctionalInterface
public interface CompositeServiceMethodInvoker<M extends Message, R extends Message>
{
Logger LOGGER = LoggerFactory.getLogger(CompositeServiceMethodInvoker.class);
ApiResult<M> invoke(InvokeContext ic, R r);
default M getCompositeResponse(R request)
throws PortalException
{
return getCompositeResponse(GetSpringContext.getInvokeContext(), request);
}
default M getCompositeResponse(InvokeContext invokeContext, R request)
throws PortalException
{
if (LOGGER.isDebugEnabled())
{
LOGGER.debug(
"Enter CompositeServiceEngine.getCompositeResponse(), identityId:{}, requestClassName:{}, request:{}",
CommonHttpUtil.getIdentity(),
request.getClass().getName(),
JsonFormatUtil.printToString(request));
}
ApiResult<M> apiResult = invoke(invokeContext, request);
if (Util.isEmpty(apiResult))
{throw new PortalException(MSResultCode.MICROSERVICE_RETURN_NULL,
(" CompositeServiceEngine.getCompositeResponse(), Call microservice error, return null, " +
"requestClassName:")
.concat(request.getClass().getName()));
}
int code = apiResult.getCode();
if (!apiResult.isSuccess())
{throw new PortalException(code,
"Call CompositeServiceEngine.getCompositeResponse() error, requestClassName:".concat(request.getClass()
.getName()));
}
else
{
M response = apiResult.getData();
if (Util.isEmpty(response))
{throw new PortalException(code,
"Call CompositeServiceEngine.getCompositeResponse() error, return null, requestClassName:".concat(
request.getClass().getName()));
}
return response;
}
}
default String getCompositeResponseCode(R request)
throws PortalException
{
ApiResult<M> apiResult = invoke(GetSpringContext.getInvokeContext(), request);
if (Util.isEmpty(apiResult))
{throw new PortalException(MSResultCode.MICROSERVICE_RETURN_NULL,
(" CompositeServiceEngine.getCompositeResponse(), Call microservice error, return null, " +
"requestClassName:{}")
.concat(request.getClass().getName()));
}
int code = apiResult.getCode();
return String.valueOf(code);
}
}
这里有3个默认方法,一个抽象方法,抽象方法返回对象ApiResult<M>。我们来看看如果用匿名内部类怎么写:
CompositeServiceMethodInvoker<GetMyDescResponse, GetMyDescRequest> getMyMethodInvoker =
new CompositeServiceMethodInvoker<GetMyDescResponse, GetBookFeeDescRequest>(){
public ApiResult<GetMyDescResponse> invoke(InvokeContext context, GetMyDescRequest request)
{
ServiceController controller = createRpcController("getMyDesc", context);
ApiResult<GetMyDescResponse> result = new ApiResult<GetMyDescResponse>(controller);
stub.getMyDesc(controller, request, result);
return result;
}};
注意这里的泛型已经用具体类型替换了。如果我们使用lambda表达式,那么可以这么写:
CompositeServiceMethodInvoker<GetMyDescResponse, GetMyDescRequest> getMyMethodInvoker =
(InvokeContext context, GetBookFeeDescRequest request) -> {
ServiceController controller = createRpcController("getMyDesc", context);
ApiResult<GetMyDescResponse> result = new ApiResult<GetMyDescResponse>(controller);
stub.getMyDesc(controller, request, result);
return result;
};
现在再来看这样一种情况,如果我们刚好在某个类中已经实现了lambda所指代的代码块,比如有这么一个类BookProductConsumer:
public class MyConsumer
extends ServiceConsumer
{
public ApiResult<GetMyDescResponse> getMyDesc(InvokeContext context,
GetMyDescRequest request) {
ServiceController controller = createRpcController("getMyDesc",context);
ApiResult<GetMyDescResponse> result = new ApiResult<GetMyDescResponse>(controller);
stub.getMyDesc(controller, request, result);
return result;
}
}
这里的getMyDesc方法返回了ApiResult对象(这里接口里的泛型M已经具体为GetMyDescResponse对象了)。我们可以看到,变量getMyDescMethodInvoker所指代的方法块已经定义在了MyConsumer类的getMyDesc方法中,所以使用方法引用来替换原来的lambda表达式:
CompositeServiceMethodInvoker<GetMyDescResponse, GetMyDescRequest> getMyDescMethodInvoker = MyConsumer::getMyDesc;
这就是类的方法引用,根据方法调用的不同情况,还有对象的方法引用、类的静态方法引用、类的构造方法引用。