Kotlin生成构造函数,将默认值设置为无参数

我们来看一个数据类的类:

data class User( val userNumber: Int = -1, val name: String, val userGroups; List<String> = emptyList(), val screenName: String = "new-user" ) 

当从Kotlin调用这个函数时,它非常简单。 我可以简单地使用命名参数语法来实现。 从Java调用,我必须指定所有的值,或使用@JvmOverloads注释,它会生成以下构造函数(除了kotlin生成的默认值的位掩码的构造函数):

 User(int userNumber, @NotNull String name, @NotNull List userGroups, @NotNull String screenName) User(int userNumber, @NotNull String name, @NotNull List userGroups) User(int userNumber, @NotNull String name) User(@NotNull String name) 

现在,如果我想创建一个Java User对象相当于User(name="John Doe", userGroups=listOf("admin", "super")我不能用上面的构造函数来做。如果我把val userNumber: Int = -1放在data class声明的末尾(构造函数的生成似乎取决于可选参数定义的顺序)。哪一个是好的,因为期望kotlin生成所有的排列是会大量膨胀一些类。

Jackson这样的工具最大的问题就是不能工作,因为他们不知道使用哪个构造函数(而不是我可以特别注释其中一个生成的构造函数)。

那么,有没有办法生成一个(单个)构造函数:

 User(Integer userNumber, String name, List<String> userGroups, String screenName) { this.userNumber = (userNumber == null) ? -1 : userNumber; this.userGroups = (userGroups == null) ? Collections.emptyList() : userGroups; //... } 

目前我正在使用上面的方法,但手动定义我需要它们的构造函数。

编辑

我应该澄清,创建一个类似的构造函数是行不通的,显然是因为这两个签名都会在JVM上发生冲突。 这就是我想要的:

 data class User( val userNumber: Int = -1, val name: String, val userGroups; List<String> = emptyList(), val screenName: String = "new-user" ) { companion object { @JvmStatic @JsonCreator fun constructionSupport( @JsonProperty("userNumber") userNumber : Int?, @JsonProperty("name") name : String, @JsonProperty("userGroups") userGroups : List<String>?, @JsonProperty("screenName") screenName : String? ) = User( userNumber = userNumber ?: -1, name = name, userGroups = userGroups ?: emptyList(), screenName = screenName ?: "new-user" ) } } 

另外请注意冗余,我必须写两次属性的默认值。 我现在看到它,我怀疑是否有解决方案。 也许这对我的一个基于kapt的项目来说是一个很好的用例:)

在踢了一会之后,我想我找到了一个可能在这里很好的解决方案。 只需在同一个源文件中定义顶层函数,即可构建该对象。 也许是这样的:

 fun build_user(userNumber: Int?, name: String, userGroups: List<String>?, screenName: String?) : User { return User(if(userNumber !== null) userNumber else -1, name, if(userGroups !== null) userGroups else emptyList(), if(screenName !== null) screenName else "new-user") } 

那么当你需要的时候,你只需要从Java调用它:

 User user = UserKt.build_user(null, "Hello", null, "Porterhouse Steak"); System.out.println(user); 

从例子中输出:

 User(userNumber=-1, name=Hello, userGroups=[], screenName=Porterhouse Steak) 

该方法位于构造函数和构建器之间的某处。 它击败了一个成熟的Builder对象,并且避免了不必要的Java互操作胶水代码混乱而造成的data class混乱。

有关更多信息,请参阅包级别函数 。