解决gRPC ServerServiceDefinition addMethod泛型约束不兼容编译错误
问题
我基于带泛型的ServerServiceDefinition类现有实例修改属性,调用addMethod方法重建新实例时出现编译错误,错误提示“inference variable has incompatible equality constraints”,相关代码和错误信息如下:
代码
public ServerServiceDefinition bindService() { ServerServiceDefinition serverServiceDefinitionV1 = ProtoReflectionServiceV1.newInstance() .bindService(); MethodDescriptor<?, ?> methodDescriptorV1 = serverServiceDefinitionV1.getServiceDescriptor() .getMethods().iterator().next(); // 该服务只有一个方法 MethodDescriptor<?, ?> methodDescriptorV1Alpha = methodDescriptorV1.toBuilder() .setFullMethodName(generateFullMethodName(SERVICE_NAME, METHOD_NAME)) .setSchemaDescriptor( new ServerReflectionMethodDescriptorSupplier(METHOD_NAME)) .build(); ServiceDescriptor serviceDescriptorV1Alpha = ServiceDescriptor.newBuilder(SERVICE_NAME) .setSchemaDescriptor(new ServerReflectionFileDescriptorSupplier()) .addMethod(methodDescriptorV1Alpha) .build(); return ServerServiceDefinition.builder(serviceDescriptorV1Alpha) .addMethod(methodDescriptorV1Alpha, serverServiceDefinitionV1.getMethod( generateFullMethodName(ServerReflectionGrpc.SERVICE_NAME, METHOD_NAME)) .getServerCallHandler()) .build(); }
编译错误
error: no suitable method found for addMethod(MethodDescriptor<CAP#1,CAP#2>,ServerCallHandler<CAP#3,CAP#4>) .addMethod(methodDescriptorV1Alpha, ^ method Builder.<ReqT#1,RespT#1>addMethod(MethodDescriptor<ReqT#1,RespT#1>,ServerCallHandler<ReqT#1,RespT#1>) is not applicable (inference variable ReqT#1 has incompatible equality constraints CAP#5,CAP#1) where ReqT#1,RespT#1 are type-variables: ReqT#1 extends Object declared in method <ReqT#1,RespT#1>addMethod(MethodDescriptor<ReqT#1,RespT#1>,ServerCallHandler<ReqT#1,RespT#1>) RespT#1 extends Object declared in method <ReqT#1,RespT#1>addMethod(MethodDescriptor<ReqT#1,RespT#1>,ServerCallHandler<ReqT#1,RespT#1>) where CAP#1,CAP#2,CAP#3,CAP#4,CAP#5 are fresh type-variables: CAP#1 extends Object from capture of ? CAP#2 extends Object from capture of ? CAP#3 extends Object from capture of ? CAP#4 extends Object from capture of ? CAP#5 extends Object from capture of ?
解决方法
编译错误的核心原因是泛型通配符?导致类型推断失败:addMethod要求MethodDescriptor<ReqT, RespT>和ServerCallHandler<ReqT, RespT>的泛型类型完全匹配,但代码中两者都使用了通配符,编译器无法确认它们的泛型参数一致。
可以通过以下两种方式解决:
方式一:显式类型转换(简单直接)
将获取到的ServerCallHandler强制转换为与MethodDescriptor匹配的泛型类型:
return ServerServiceDefinition.builder(serviceDescriptorV1Alpha) .addMethod(methodDescriptorV1Alpha, (ServerCallHandler<Object, Object>) serverServiceDefinitionV1.getMethod( generateFullMethodName(ServerReflectionGrpc.SERVICE_NAME, METHOD_NAME)) .getServerCallHandler()) .build();
如果明确知道请求和响应的具体类型,替换为对应的实际类型(比如ServerCallHandler<MyRequest, MyResponse>)会更安全。
方式二:引入辅助方法固化泛型类型(更安全)
编写一个泛型辅助方法,让编译器能明确推断出一致的类型参数:
private <ReqT, RespT> void addMatchingMethod( ServerServiceDefinition.Builder builder, MethodDescriptor<ReqT, RespT> methodDescriptor, ServerCallHandler<ReqT, RespT> callHandler) { builder.addMethod(methodDescriptor, callHandler); }
然后在原代码中调用该方法:
ServerServiceDefinition.Builder builder = ServerServiceDefinition.builder(serviceDescriptorV1Alpha); addMatchingMethod(builder, methodDescriptorV1Alpha, serverServiceDefinitionV1.getMethod( generateFullMethodName(ServerReflectionGrpc.SERVICE_NAME, METHOD_NAME)) .getServerCallHandler()); return builder.build();
这种方式无需强制类型转换,类型安全性更高。
内容的提问来源于stack exchange,提问作者Kannan J
相关产品推荐
相关产品推荐

