Kotlin中继承Exception并实现GraphQLError时如何解决意外覆盖问题
解决Kotlin中ShopException继承Exception并实现GraphQLError的方法冲突问题
这个问题的核心是Java和Kotlin对方法签名的解析差异导致的冲突:
- Java的
Exception类自带public String getMessage()方法,在Kotlin中会被自动识别为val message: String?的getter方法,其JVM签名是<get-message>()。 - 而
GraphQLError接口要求实现的getMessage(): String!方法,在JVM上的签名和前者完全一致,因此触发了“Accidental override”的冲突。
解决方案:使用@JvmName注解修改方法的JVM签名
我们可以通过@JvmName注解,将实现GraphQLError接口的getMessage()方法重命名,避免和父类Exception的方法签名冲突。同时处理返回值的兼容性(Exception的message是可空类型,而GraphQLError要求非空):
import graphql.GraphQLError import graphql.ErrorType enum class ErrorCode { INVALID_INPUT, RESOURCE_NOT_FOUND, PERMISSION_DENIED } class ShopException(val code: ErrorCode) : Exception(code.name), GraphQLError { // 用@JvmName修改JVM层面的方法名,避开和Exception的getMessage()冲突 @JvmName("getGraphQLErrorMessage") override fun getMessage(): String { // 优先使用父类的message,为空则返回ErrorCode对应的描述 return message ?: when(code) { ErrorCode.INVALID_INPUT -> "输入参数无效" ErrorCode.RESOURCE_NOT_FOUND -> "请求的资源不存在" ErrorCode.PERMISSION_DENIED -> "没有操作权限" } } // 实现GraphQLError的其他必要方法,根据业务需求返回对应值 override fun getLocations(): MutableList<GraphQLError.Location>? = null override fun getErrorType(): ErrorType? = ErrorType.ValidationError override fun getExtensions(): MutableMap<String, Any>? { return mutableMapOf("errorCode" to code.name) } }
原理说明
@JvmName注解会改变该方法在JVM字节码中的名称,让它变成getGraphQLErrorMessage,这样就不会和Exception继承来的<get-message>()方法签名重复。而Kotlin编译器会自动处理接口方法的映射,确保GraphQLError的方法调用能正确指向我们重命名后的方法。
这种方式不需要修改父类Exception的任何代码,完美适配你无法控制父类字段的场景。
内容的提问来源于stack exchange,提问作者Alkis Mavridis
相关产品推荐
相关产品推荐

