含Value Class属性的Kotlin数据类无参构造器异常排查
Kotlin值类导致数据类无参构造器生成异常问题
问题场景
首先定义一个值类Id:
@JvmInline value class Id private constructor(val value: String) { companion object { @JvmStatic @JsonCreator fun generate() = Id(randomUUID().toString()) } }
再定义一个所有属性都带默认值的数据类:
data class TestDataClass( var id: Id? = null, var string: String? = null, )
根据Kotlin官方文档,当数据类的所有属性都有默认值时,编译器应当自动生成无参构造器,但使用如下Java代码调用时会抛出NoSuchMethodException:
// 抛出NoSuchMethodException System.out.println(TestDataClass.class.getConstructor());
测试验证的其他现象
- 将
Id改为普通类后,数据类能正常生成无参构造器,符合预期。 - 添加no-args插件后,上述带可空值类默认值的数据类仍无法生成无参构造器,但移除
id的默认值并添加@NoArgs注解后,却能成功生成无参构造器:
@NoArgs data class TestDataClass( var id: Id, var string: String? = null, )
- 只要
Id是普通类,无论是否使用默认值、是否添加no-args插件,所有情况均符合预期。
原因分析
这是Kotlin编译器处理可空值类属性默认值时的bug。值类作为内联类,编译阶段会被特殊处理,当数据类中存在Id? = null这类可空值类属性且指定默认值时,编译器生成Java无参构造器的逻辑出现异常,没有正确识别该属性的默认值有效性,进而跳过了无参构造器的生成流程。
而移除id的默认值并使用@NoArgs插件时,插件会强制触发无参构造器的生成逻辑,不受值类特殊处理的影响;当Id改为普通类时,编译器的常规默认值处理逻辑就能正常运行,生成预期的无参构造器。
内容的提问来源于stack exchange,提问作者Rad
相关产品推荐
相关产品推荐

