[英]How can I instantiate an object using default constructor parameter values in Kotlin?
I have data class with default values. 我有带有默认值的数据类。
data class Project(
val code: String,
val name: String,
val categories: List<String> = emptyList())
Java reflection fails to instantiate the class when some values are null. 当某些值为空时,Java反射无法实例化该类。 I'm getting exception 我要例外了
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method Project.<init>, parameter categories
This is because java.lang.reflect.Constructor<T>.instantiateClass
method expects arguments that are not null. 这是因为java.lang.reflect.Constructor<T>.instantiateClass
方法期望的参数不为null。
I have the type information, I have the constructor definition but I'm not sure how to call the constructor so that it uses the default values (The values are coming from the database and categories
can be null
). 我有类型信息,我有构造函数定义,但是我不确定如何调用构造函数,以便它使用默认值(这些值来自数据库, categories
可以为null
)。 Is there any way to achieve this in Kotlin? 在Kotlin中有什么方法可以做到这一点?
The Kotlin default parameters are not compatible with Java reflection, meaning there's no simple way to use them together, because the Kotlin default parameters actually work with a separate method under the hood that is also passed a bit mask to specify which arguments are default. Kotlin默认参数与Java反射不兼容,这意味着没有简单的方法可以将它们一起使用,因为Kotlin默认参数实际上与幕后的另一种方法一起使用,该方法还传递了一个位掩码来指定哪些参数为默认值。
There are two ways to fix this. 有两种方法可以解决此问题。
Use Kotlin reflection. 使用Kotlin反射。 For example, the callBy
function supports default parameters, they can be omitted from the map. 例如, callBy
函数支持默认参数,可以将其从映射中省略。
Use @JvmOverloads
to generate an overload without the default parameter which can be called in Java. 使用@JvmOverloads
生成没有默认参数的重载,该参数可以在Java中调用。
@JvmOverloads data class Project( val code: String, val name: String, val categories: List<String> = emptyList() )
Using in Kotlin: 在Kotlin中使用:
default values in constructors are taken only when the particular parameter of that constructor is not passed to it at all .That means it is done to achieve various combination of parameteraised constructor. 仅当构造函数的特定参数根本没有传递给构造函数的默认值时才使用它的默认值。这意味着它已完成以实现参数化构造函数的各种组合。 for example, 例如,
data class Bird (val name: String = "peacock", val gender: String = "male")
takes default values when used as Bird(), Bird("dove") or Bird(gender ="female") . 当用作Bird(),Bird(“ dove”)或Bird(gender =“ female”)时,采用默认值。
so to solve your issue you have to add ? 所以要解决您的问题,您必须添加? next to the categories parameter. 类别参数旁边。 like this, 像这样,
data class Project(val code: String,
val name: String,
val categories: List<String>?)
and no need for emptyList() default. 并且不需要默认的emptyList()。 When you using emptyList as in your question you have to check for null and omit that parameter like this 当您在问题中使用emptyList时,您必须检查null并省略该参数,如下所示
val project = if(categories == null)
{
Project(code,name)
}
else
{
Project(code,name,categories)
}
That is when using this data class in another kotlin class . 那就是在另一个kotlin类中使用此数据类时。
Using in JAVA: 在JAVA中使用:
But if you want to use this data class in any java class then as @Hotkey said it is not supported by default , as kotlin supports this default parameter by using some methods under the hood. 但是,如果要在任何Java类中使用此数据类,则正如@Hotkey所说,默认情况下不支持此数据类,因为kotlin通过使用一些内部方法支持此默认参数。
So to make it compatible with java class you have to add @JvmOverloads annotation but not as @Hotkey said it have to annotated like this 因此,要使其与Java类兼容,您必须添加@JvmOverloads批注,但不必像@Hotkey所说的那样进行批注
data class Project @JvmOverloads constructor(val code: String,
val name: String,
val categories: List<String>? = emptyList())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.