jdk1.8新特性之方法引用

  方法引用其实就是方法调用,符号是两个冒号::来表示,左边是对象或类,右边是方法。它其实就是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;

  这就是类的方法引用,根据方法调用的不同情况,还有对象的方法引用、类的静态方法引用、类的构造方法引用。