You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin中实现等价于Java原始泛型的Serializer且不修改register签名?

Kotlin泛型Serializer实现问题:将Java原始泛型实现转为纯Kotlin

已定义的Kotlin泛型接口与类

Transformer接口

interface Transformer<T, R> {
    fun transform(it: T): R
}

DefaultNullableTransformer类

该类用于处理空输入,将非空值委托给非空Transformer:

data class DefaultNullableTransformer<T, R>(
    val transformer: Transformer<T, R>,
    val default: R
) : Transformer<T?, R> {
    override fun transform(it: T?): R {
        val data = it ?: return default
        return transformer.transform(data)
    }
}

自定义序列化框架核心类

interface Serializer<T, D> {
    fun serialize(it: T, registry: SerializerRegistry): D
    fun deserialize(it: D, registry: SerializerRegistry): T
}

data class TypedData<T : Any>(val type: KClass<out T>, val data: Any)

class SerializerRegistry(private val defaultSerializer: Serializer<*, *>? = null) {
    private val serializers = mutableMapOf<KClass<*>, Serializer<*, *>>()

    fun <T : Any> register(type: KClass<T>, serializer: Serializer<T, *>) {
        serializers[type] = serializer
    }

    fun <T : Any> serialize(it: T) = TypedData(
        it::class,
        get(it::class).serialize(it, this)
    )

    fun <T : Any> deserialize(it: TypedData<T>): T = get(it.type).deserialize(it.data, this) as T

    private fun get(type: KClass<out Any>): Serializer<Any?, Any> {
        val serializer: Serializer<Any?, Any>? = serializers[type] as? Serializer<Any?, Any> ?: (defaultSerializer as Serializer<Any?, Any>?)
        return serializer ?: throw UnsupportedOperationException("Serializer for $type is not registered")
    }
}

问题描述

我在实现类型擦除的Serializer时遇到了阻碍。在Java中,我可以通过原始泛型实现DefaultNullableTransformerSerializer,代码如下:

Java原始泛型实现

public class DefaultNullableTransformerSerializer implements Serializer<DefaultNullableTransformer, DefaultNullableTransformerSerializer.SerializedData> {
    @Override
    public SerializedData serialize(DefaultNullableTransformer transformer, SerializerRegistry registry) {
        TypedData<Transformer> transformerData = registry.serialize(transformer.getTransformer());
        Optional<TypedData<?>> defaultData = Optional.ofNullable(transformer.getDefault()).map(registry::serialize);
        return new SerializedData(transformerData, defaultData.orElse(null));
    }

    @Override
    public DefaultNullableTransformer deserialize(SerializedData data, SerializerRegistry registry) {
        Transformer transformer = registry.deserialize(data.getTransformer());
        Object defaultObj = data.getDefault() != null ? registry.deserialize(data.getDefault()) : null;
        return new DefaultNullableTransformer<>(transformer, defaultObj);
    }

    public static class SerializedData {
        private final TypedData<Transformer> transformer;
        private final TypedData<?> defaultData;

        public SerializedData(TypedData<Transformer> transformer, TypedData<?> defaultData) {
            this.transformer = transformer;
            this.defaultData = defaultData;
        }

        public TypedData<Transformer> getTransformer() {
            return transformer;
        }

        public TypedData<?> getDefault() {
            return defaultData;
        }
    }
}

该Java类可以通过以下代码正常注册:

register(DefaultNullableTransformer::class, DefaultNullableTransformerSerializer())

但我尝试用Any?和*将其转换为Kotlin时始终失败。我知道Kotlin的类型系统比Java更严格,想请教:是否可以在不修改SerializerRegistry.register方法签名的前提下,用纯Kotlin实现同样的功能?

另外,我还尝试了带泛型参数的Java实现:

带泛型参数的Java实现

public class DefaultNullableTransformerSerializer<T, R> implements Serializer<DefaultNullableTransformer<T, R>, DefaultNullableTransformerSerializer.SerializedData<T, R>> {

    @Override
    public SerializedData<T, R> serialize(DefaultNullableTransformer<T, R> transformer, SerializerRegistry registry) {
        TypedData<Transformer<T, R>> transformerData = registry.serialize(transformer.getTransformer());
        Optional<TypedData<?>> defaultData = Optional.ofNullable(transformer.getDefault()).map(registry::serialize);
        return new SerializedData<>(transformerData, defaultData.orElse(null));
    }

    @Override
    public DefaultNullableTransformer<T, R> deserialize(SerializedData<T, R> data, SerializerRegistry registry) {
        Transformer<T, R> transformer = registry.deserialize(data.getTransformer());
        Object defaultObj = data.getDefault() != null ? registry.deserialize(data.getDefault()) : null;
        return new DefaultNullableTransformer<>(transformer, (R) defaultObj);
    }

    public static class SerializedData<T, R> {
        private final TypedData<Transformer<T, R>> transformer;
        private final TypedData<?> defaultData;

        public SerializedData(TypedData<Transformer<T, R>> transformer, TypedData<?> defaultData) {
            this.transformer = transformer;
            this.defaultData = defaultData;
        }

        public TypedData<Transformer<T, R>> getTransformer() {
            return transformer;
        }

        public TypedData<?> getDefault() {
            return defaultData;
        }
    }
}

但用register(DefaultNullableTransformer::class, DefaultNullableTransformerSerializer())注册时会出现类型不匹配,无法编译。


内容的提问来源于stack exchange,提问作者alturkovic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 14:39:57