方法引用其實就是方法調用,符號是兩個冒號::來表示,左邊是對象或類,右邊是方法。它其實就是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;
這就是類的方法引用,根據方法調用的不同情況,還有對象的方法引用、類的靜態方法引用、類的構造方法引用。