简体   繁体   English

如何在Kotlin中使用默认构造函数参数值实例化对象?

[英]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. 有两种方法可以解决此问题。

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.

相关问题 Java:如何在不使用父构造函数的情况下从子对象实例化父对象? - Java: How can I instantiate a parent object from child without using parent constructor? 我该如何在jUnit中实例化一个对象,该对象需要在其构造函数中反射地创建另一个对象? - How can I instantiate an object in jUnit, that needs to reflectively create another object inside its constructor? 我可以在纯 Kotlin 中通过类名实例化一个对象吗 - Can I instantiate an object by the class name in pure Kotlin 使用接受字符串参数的构造函数实例化一个类对象? - Instantiate a class object with constructor that accepts a string parameter? 如何使用反射获取默认构造函数参数? - How to get default constructor parameter using reflection? 如何使用 Kotlin Refelction 调用构造函数默认值 lambda? - How to call constructor default lambda using Kotlin Refelction? 使用构造函数参数使用反射实例化对象 - instantiate object with reflection using constructor arguments 如何获取非大小写类的构造函数参数的默认值? - How can I obtain the default value of a constructor parameter for a non-case class? 通过调用隐式默认构造函数实例化给定 class 的 object - Instantiate object of given class by invoking implicit default constructor 如何获取 Kotlin 构造函数参数的 KClass - How to get the KClass for a Kotlin constructor parameter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM