Java无法访问kotlinx-serialization生成类Companion的serializer方法
在Java代码中集成kotlinx serialization框架时,无法通过Companion对象访问Kotlin序列化插件自动生成的静态serializer()方法,直接触发编译失败。
- Kotlin侧声明可序列化类代码:
@kotlinx.serialization.Serializable data class MyData(private val data: String)
- Maven项目pom.xml配置:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>TestProject</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>18</maven.compiler.source> <maven.compiler.target>18</maven.compiler.target> <kotlin.version>1.7.0</kotlin.version> <serialization.version>1.3.3</serialization.version> </properties> <dependencies> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-stdlib-jdk8</artifactId> <version>${kotlin.version}</version> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-test</artifactId> <version>${kotlin.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jetbrains.kotlinx</groupId> <artifactId>kotlinx-serialization-json-jvm</artifactId> <version>1.3.3</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <version>${kotlin.version}</version> <executions> <execution> <id>compile</id> <phase>compile</phase> <goals> <goal>compile</goal> </goals> </execution> <execution> <id>test-compile</id> <phase>test-compile</phase> <goals> <goal>test-compile</goal> </goals> </execution> </executions> <configuration> <jvmTarget>1.8</jvmTarget> <compilerPlugins> <plugin>kotlinx-serialization</plugin> </compilerPlugins> </configuration> <dependencies> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-serialization</artifactId> <version>${kotlin.version}</version> </dependency> </dependencies> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>17</source> <target>17</target> </configuration> </plugin> </plugins> </build>
- 编译失败的Java调用代码:
public class Main { public static void main(String[] args) { // 编译报错,无法在Companion对象下找到serializer()方法 MyData.Companion.serializer(); } }
- 其他Kotlin序列化类(例如
JsonElement)的Companion.serializer()方法可正常访问,仅当前项目中通过插件自动生成序列化逻辑的类存在该问题 - 反编译编译生成的MyData类文件,可见类内确实存在Companion对象,但Companion内部无任何方法,反编译stub代码如下:
// IntelliJ API Decompiler stub source generated from a class file // Implementation of methods is not available @kotlinx.serialization.Serializable public final data class MyData public constructor(data: kotlin.String) { public companion object { } @kotlin.Deprecated public constructor(seen1: kotlin.Int, data: kotlin.String?, serializationConstructorMarker: kotlinx.serialization.internal.SerializationConstructorMarker?) { /* compiled code */ } private final val data: kotlin.String /* compiled code */ private final operator fun component1(): kotlin.String { /* compiled code */ } @kotlin.Deprecated public object `$serializer` : kotlinx.serialization.internal.GeneratedSerializer<MyData> { } }
- MyData类自动生成的
copy()等常规方法可正常在Java中调用
kotlinx serialization 1.3+版本的编译插件,针对未定义任何成员的空companion object,不会将生成的serializer()方法挂载到Companion类的实例上,而是直接生成类级别的静态方法,同时生成独立的$serializer内部实现对象。
而JsonElement等官方库内置的序列化类,在定义时就显式给Companion对象声明了serializer()方法,因此可以通过Companion正常调用。
方案1:直接调用类静态方法(无侵入,推荐)
不需要修改Kotlin侧代码,直接跳过Companion,调用类上生成的静态serializer()方法即可:
public class Main { public static void main(String[] args) { KSerializer<MyData> myDataSerializer = MyData.serializer(); // 后续序列化逻辑 } }
如果IDEA暂时提示方法不存在,先执行一次mvn compile触发插件代码生成,索引刷新后即可正常识别。
方案2:调用插件生成的内部序列化实例
插件会在类中生成静态的$serializer实现对象,可以直接获取该实例使用:
public class Main { public static void main(String[] args) { KSerializer<MyData> myDataSerializer = MyData.$serializer.INSTANCE; } }
注意:$serializer属于插件生成的内部API,带有@Deprecated标记,不保证跨版本兼容性,仅作为临时方案使用。
方案3:Kotlin侧显式声明Companion的序列化能力
如果需要保留MyData.Companion.serializer()的调用习惯,可以修改Kotlin类定义,给companion object显式委托序列化实现,让Companion实例持有对应方法:
@kotlinx.serialization.Serializable data class MyData(private val data: String) { companion object : KSerializer<MyData> by serializer() }
修改后Java侧即可正常通过Companion对象调用serializer()方法。
内容的提问来源于stack exchange,提问作者Barracuda

