ros*_*euz 5 reflection kotlin kotlin-reflect kotlin-null-safety
我有默认值的数据类。
data class Project(
val code: String,
val name: String,
val categories: List<String> = emptyList())
Run Code Online (Sandbox Code Playgroud)
当某些值为空时,Java 反射无法实例化类。我得到了例外
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method Project.<init>, parameter categories
Run Code Online (Sandbox Code Playgroud)
这是因为java.lang.reflect.Constructor<T>.instantiateClass方法需要不为空的参数。
我有类型信息,我有构造函数定义,但我不确定如何调用构造函数以便它使用默认值(这些值来自数据库并且categories可以是null)。有没有办法在 Kotlin 中实现这一目标?
Kotlin 默认参数与 Java 反射不兼容,这意味着没有简单的方法可以将它们一起使用,因为 Kotlin 默认参数实际上与一个单独的方法一起工作,该方法还传递了一个位掩码来指定哪些参数是默认的。
有两种方法可以解决这个问题。
使用 Kotlin 反射。例如,该callBy函数支持默认参数,它们可以从映射中省略。
使用@JvmOverloads产生不默认参数的重载,可以在Java中被调用。
@JvmOverloads
data class Project(
val code: String,
val name: String,
val categories: List<String> = emptyList()
)
Run Code Online (Sandbox Code Playgroud)Vel*_*n V -1
在 Kotlin 中使用:
仅当该构造函数的特定参数根本未传递给构造函数时,才会采用构造函数中的默认值。这意味着这样做是为了实现参数化构造函数的各种组合。例如,
data class Bird (val name: String = "peacock", val gender: String = "male")
Run Code Online (Sandbox Code Playgroud)
用作 Bird()、Bird("dove") 或 Bird(gender ="female") 时采用默认值。
所以要解决你的问题,你必须添加 ? 在类别参数旁边。像这样,
data class Project(val code: String,
val name: String,
val categories: List<String>?)
Run Code Online (Sandbox Code Playgroud)
并且不需要emptyList()默认值。当您在问题中使用 emptyList 时,您必须检查 null 并省略该参数,如下所示
val project = if(categories == null)
{
Project(code,name)
}
else
{
Project(code,name,categories)
}
Run Code Online (Sandbox Code Playgroud)
那是在另一个 kotlin 类中使用这个数据类时。
在JAVA中使用:
但是如果你想在任何 java 类中使用这个数据类,那么正如 @Hotkey 所说,默认情况下不支持它,因为 kotlin 通过使用一些底层方法来支持这个默认参数。
因此,为了使其与 java 类兼容,您必须添加@JvmOverloads注释,但不能像 @Hotkey 所说的那样必须这样注释
data class Project @JvmOverloads constructor(val code: String,
val name: String,
val categories: List<String>? = emptyList())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1514 次 |
| 最近记录: |