方法引用其实就是方法调用,符号是两个冒号::来表示,左边是对象或类,右边是方法。它其实就是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)) { LOGGER.error( " CompositeServiceEngine.getCompositeResponse(), Call microservice error, return null, identityId:{}," + " requestClassName:{}, request:{}", CommonHttpUtil.getIdentity(), request.getClass().getName(), JsonFormatUtil.printToString(request)); 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()) { LOGGER.error( "Call CompositeServiceEngine.getCompositeResponse() error, identityId:{}, requestClassName:{}, " + "request:{}, return code:{}", CommonHttpUtil.getIdentity(), request.getClass().getName(), JsonFormatUtil.printToString(request), code); throw new PortalException(code, "Call CompositeServiceEngine.getCompositeResponse() error, requestClassName:".concat(request.getClass() .getName())); } else { M response = apiResult.getData(); if (Util.isEmpty(response)) { LOGGER.error( "Call CompositeServiceEngine.getCompositeResponse() error,return null, identityId:{}, " + "requestClassName:{}, request:{}, return code:{}", CommonHttpUtil.getIdentity(), request.getClass().getName(), JsonFormatUtil.printToString(request), code); throw new PortalException(code, "Call CompositeServiceEngine.getCompositeResponse() error, return null, requestClassName:".concat( request.getClass().getName())); } if (LOGGER.isDebugEnabled()) { LOGGER.debug( "Exit CompositeServiceEngine.getCompositeResponse(), identityId:{}, requestClasssName:{}, " + "request:{}, result:{}", CommonHttpUtil.getIdentity(), request.getClass().getName(), JsonFormatUtil.printToString(request), JsonFormatUtil.printToString(response)); } return response; } } default String getCompositeResponseCode(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(GetSpringContext.getInvokeContext(), request); if (Util.isEmpty(apiResult)) { LOGGER.error( " CompositeServiceEngine.getCompositeResponse(), Call microservice error, return null, " + "identityId:{}, requestClassName:{}, request:{}", CommonHttpUtil.getIdentity(), request.getClass().getName(), JsonFormatUtil.printToString(request)); throw new PortalException(MSResultCode.MICROSERVICE_RETURN_NULL, (" CompositeServiceEngine.getCompositeResponse(), Call microservice error, return null, " + "requestClassName:{}") .concat(request.getClass().getName())); } int code = apiResult.getCode(); if (LOGGER.isDebugEnabled()) { LOGGER.debug( "Exit CompositeServiceEngine.getCompositeResponse(), identityId:{}, requestClassName:{}, result:{}", CommonHttpUtil.getIdentity(), request.getClass().getName(), code); } return String.valueOf(code); } }
这里有3个默认方法,一个抽象方法,抽象方法返回对象ApiResult<M>。我们来看看如果用匿名内部类怎么写:
CompositeServiceMethodInvoker<GetBookFeeDescResponse, GetBookFeeDescRequest> getBooFeeDescMethodInvoker = new CompositeServiceMethodInvoker<GetBookFeeDescResponse, GetBookFeeDescRequest>(){ public ApiResult<GetBookFeeDescResponse> invoke(InvokeContext context, GetBookFeeDescRequest request) { ServiceController controller = createRpcController("getBookFeeDesc", context); ApiResult<GetBookFeeDescResponse> result = new ApiResult<GetBookFeeDescResponse>(controller); stub.getBookFeeDesc(controller, request, result); return result; }};
注意这里的泛型已经用具体类型替换了。如果我们使用lambda表达式,那么可以这么写:
CompositeServiceMethodInvoker<GetBookFeeDescResponse, GetBookFeeDescRequest> getBooFeeDescMethodInvoker = (InvokeContext context, GetBookFeeDescRequest request) -> { ServiceController controller = createRpcController("getBookFeeDesc", context); ApiResult<GetBookFeeDescResponse> result = new ApiResult<GetBookFeeDescResponse>(controller); stub.getBookFeeDesc(controller, request, result); return result; };
现在再来看这样一种情况,如果我们刚好在某个类中已经实现了lambda所指代的代码块,比如有这么一个类BookProductConsumer:
public class BookProductConsumer extends ServiceConsumer { public ApiResult<GetBookFeeDescResponse> getBookFeeDesc(InvokeContext context, GetBookFeeDescRequest request) { ServiceController controller = createRpcController("getBookFeeDesc",context); ApiResult<GetBookFeeDescResponse> result = new ApiResult<GetBookFeeDescResponse>(controller); stub.getBookFeeDesc(controller, request, result); return result; } }
这里的getBookFeeDesc方法返回了ApiResult对象(这里接口里的泛型M已经具体为GetBookFeeDescResponse对象了)。我们可以看到,变量getBooFeeDescMethodInvoker所指代的方法块已经定义在了BookProductConsumer类的getBookFeeDesc方法中,所以使用方法引用来替换原来的lambda表达式:
CompositeServiceMethodInvoker<GetBookFeeDescResponse, GetBookFeeDescRequest> getBooFeeDescMethodInvoker = BookProductConsumer::getBookFeeDesc;
这就是类的方法引用,根据方法调用的不同情况,还有对象的方法引用、类的静态方法引用、类的构造方法引用。