Scala泛型场景下无法解析重载serialize方法问题排查
Scala通用序列化器重载方法解析报错问题
问题场景
在Scala中实现适配业务场景的通用序列化器时,初始实现代码如下:
class X[V]() extends Codec[V] { override def serialize(data :V): Array[Byte] = { val serialization = TimedAction(SerializationUtils.serialize(data)) val uncompressedBytes = serialization.resultUnsafe uncompressedBytes } }
编码时遇到报错:Cannot resolve overloaded method 'serialize',初步判断问题与泛型使用相关。
报错关联类为org.apache.commons.lang3包下的SerializationUtils,该类中两个serialize重载方法定义如下:
public static byte[] serialize(final Serializable obj) {} public static void serialize(final Serializable obj, final OutputStream outputStream) {}
待解决疑问
- 两个方法的签名存在明确差异,为什么仍会出现无法解析重载方法的报错?
- 该报错要如何修复?如果需要明确调用仅接收单个
Serializable类型参数、返回byte数组的serialize方法,是否有方式可以直接指定调用该重载版本?
问题解答
报错原因
报错和重载方法签名区分度无关,核心触发原因是泛型缺少类型边界约束:
代码中定义的泛型V没有声明任何上界,编译器无法确认V类型的实例一定实现了java.io.Serializable接口。
Scala编译器做重载解析时,会先校验传入参数是否满足候选方法的参数类型要求:无约束的V类型既不匹配第一个单参方法要求的Serializable入参,也不匹配第二个双参方法要求的第一个Serializable入参,没有任何一个重载版本符合入参类型要求,最终抛出无法解析重载方法的错误。
修复方案
有两种可行修复方式,优先推荐第一种:
- 给泛型
V添加Serializable上界约束,从类型层面保证入参符合方法要求,编译器即可自动匹配到正确的单参重载版本:import java.io.Serializable class X[V <: Serializable]() extends Codec[V] { override def serialize(data : V): Array[Byte] = { val serialization = TimedAction(SerializationUtils.serialize(data)) val uncompressedBytes = serialization.resultUnsafe uncompressedBytes } } - 如果业务场景不允许修改泛型边界,可以在调用方法时对入参做显式类型转换,明确指定入参为
Serializable类型,强制匹配对应重载:
注意该方案存在运行时风险:如果实际传入的val serialization = TimedAction(SerializationUtils.serialize(data.asInstanceOf[Serializable]))data对象未实现Serializable接口,会抛出类型转换异常。
内容的提问来源于stack exchange,提问作者Freez
相关产品推荐
相关产品推荐

