如何在Kotlin Android中为数据类创建空构造函数

如何在Kotlin Android中为数据类创建空构造函数,android,kotlin,Android,Kotlin,我在Kotlin数据类中声明了10多个变量,我想为它创建一个空构造函数,就像我们在Java中通常做的那样 数据类: data class Activity( var updated_on: String, var tags: List<String>, var description: String, var user_id: List<Int>, var status_id: Int, var title: String,

我在Kotlin数据类中声明了10多个变量,我想为它创建一个空构造函数,就像我们在Java中通常做的那样

数据类:

data class Activity(
    var updated_on: String,
    var tags: List<String>,
    var description: String,
    var user_id: List<Int>,
    var status_id: Int,
    var title: String,
    var created_at: String,
    var data: HashMap<*, *>,
    var id: Int,
    var counts: LinkedTreeMap<*, *>,
)
但是数据类要求在创建构造函数时传递所有参数。我们如何像Java POJO类构造函数那样简化它

val activity =  Activity(null,null,null,null,null,"New Computer",null,null,null,null)
sendToServer(activity)

这里有两个选项:

  • 为每个参数指定默认值:

    data class Activity(
        var updated_on: String = "",
        var tags: List<String> = emptyList(),
        var description: String = "",
        var user_id: List<Int> = emptyList(),
        var status_id: Int = -1,
        var title: String = "",
        var created_at: String = "",
        var data: HashMap<*, *> = hashMapOf<Any, Any>(),
        var id: Int = -1,
        var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
    ) 
    
    data class Item(var id: String = "",
                var title: String = "",
                var condition: String = "",
                var price: String = "",
                var categoryId: String = "",
                var make: String = "",
                var model: String = "",
                var year: String = "",
                var bodyStyle: String = "",
                var detail: String = "",
                var latitude: Double = 0.0,
                var longitude: Double = 0.0,
                var listImages: List<String> = emptyList(),
                var idSeller: String = "")
    
    data class Activity(
        var updated_on: String = "",
        var tags: List<String> = emptyList(),
        var description: String = "",
        var user_id: List<Int> = emptyList(),
        var status_id: Int = -1,
        var title: String = "",
        var created_at: String = "",
        var data: HashMap<*, *> = hashMapOf<Any, Any>(),
        var id: Int = -1,
        var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
    )
    

    并非每个类都需要是
    数据类,反之亦然。事实上,根据我的经验,我发现数据类在涉及一些复杂业务逻辑的领域特别有用

    除了@miensol answer,我还要补充一些细节:

    如果您想要使用数据类的Java可见空构造函数,则需要明确地定义它

    使用默认值+构造函数说明符非常简单:

    data class Activity(
        var updated_on: String = "",
        var tags: List<String> = emptyList(),
        var description: String = "",
        var user_id: List<Int> = emptyList(),
        var status_id: Int = -1,
        var title: String = "",
        var created_at: String = "",
        var data: HashMap<*, *> = hashMapOf<Any, Any>(),
        var id: Int = -1,
        var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
    ) {
        constructor() : this(title = "") // this constructor is an explicit
                                         // "empty" constructor, as seen by Java.
    }
    
    数据类活动(
    var更新日期:String=“”,
    变量标记:List=emptyList(),
    变量说明:String=“”,
    var user_id:List=emptyList(),
    变量状态_id:Int=-1,
    var title:String=“”,
    在以下位置创建变量:String=“”,
    变量数据:HashMap=hashMapOf(),
    变量id:Int=-1,
    变量计数:LinkedTreeMap=LinkedTreeMap()
    ) {
    构造函数():this(title=”“)//此构造函数是显式的
    //“空”构造函数,如Java所示。
    }
    

    这意味着,使用此技巧,您现在可以使用标准Java序列化程序(Jackson、Gson等)序列化/反序列化此对象。

    如果您为所有字段提供默认值,则Kotlin会自动生成空构造函数

    data class User(var id: Long = -1,
                    var uniqueIdentifier: String? = null)
    
    您只需拨打:

    val user = User()
    

    如果为每个主构造函数参数指定默认值:

    data class Activity(
        var updated_on: String = "",
        var tags: List<String> = emptyList(),
        var description: String = "",
        var user_id: List<Int> = emptyList(),
        var status_id: Int = -1,
        var title: String = "",
        var created_at: String = "",
        var data: HashMap<*, *> = hashMapOf<Any, Any>(),
        var id: Int = -1,
        var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
    ) 
    
    data class Item(var id: String = "",
                var title: String = "",
                var condition: String = "",
                var price: String = "",
                var categoryId: String = "",
                var make: String = "",
                var model: String = "",
                var year: String = "",
                var bodyStyle: String = "",
                var detail: String = "",
                var latitude: Double = 0.0,
                var longitude: Double = 0.0,
                var listImages: List<String> = emptyList(),
                var idSeller: String = "")
    
    data class Activity(
        var updated_on: String = "",
        var tags: List<String> = emptyList(),
        var description: String = "",
        var user_id: List<Int> = emptyList(),
        var status_id: Int = -1,
        var title: String = "",
        var created_at: String = "",
        var data: HashMap<*, *> = hashMapOf<Any, Any>(),
        var id: Int = -1,
        var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
    )
    

    Kotlin中数据类的非空辅助构造函数:

    data class ChemicalElement(var name: String,
                               var symbol: String,
                               var atomicNumber: Int,
                               var atomicWeight: Double,
                               var nobleMetal: Boolean?) {
    
        constructor(): this("Silver",
                            "Ag", 
                            47,
                            107.8682,
                            true)
    }
    
    fun main() {
        var chemicalElement = ChemicalElement()
        println("RESULT: ${chemicalElement.symbol} means ${chemicalElement.name}")
        println(chemicalElement)
    }
    
    // RESULT: Ag means Silver
    // ChemicalElement(name=Silver, symbol=Ag, atomicNumber=47, atomicWeight=107.8682, nobleMetal=true)
    
    data class ChemicalElement(var name: String,
                               var symbol: String,
                               var atomicNumber: Int,
                               var atomicWeight: Double,
                               var nobleMetal: Boolean?) {
    
        constructor(): this("",
                            "", 
                            -1,
                            0.0,
                            null)
    }
    
    fun main() {
        var chemicalElement = ChemicalElement()
        println(chemicalElement)
    }
    
    // ChemicalElement(name=, symbol=, atomicNumber=-1, atomicWeight=0.0, nobleMetal=null)
    
    Kotlin中数据类的二级构造函数为空:

    data class ChemicalElement(var name: String,
                               var symbol: String,
                               var atomicNumber: Int,
                               var atomicWeight: Double,
                               var nobleMetal: Boolean?) {
    
        constructor(): this("Silver",
                            "Ag", 
                            47,
                            107.8682,
                            true)
    }
    
    fun main() {
        var chemicalElement = ChemicalElement()
        println("RESULT: ${chemicalElement.symbol} means ${chemicalElement.name}")
        println(chemicalElement)
    }
    
    // RESULT: Ag means Silver
    // ChemicalElement(name=Silver, symbol=Ag, atomicNumber=47, atomicWeight=107.8682, nobleMetal=true)
    
    data class ChemicalElement(var name: String,
                               var symbol: String,
                               var atomicNumber: Int,
                               var atomicWeight: Double,
                               var nobleMetal: Boolean?) {
    
        constructor(): this("",
                            "", 
                            -1,
                            0.0,
                            null)
    }
    
    fun main() {
        var chemicalElement = ChemicalElement()
        println(chemicalElement)
    }
    
    // ChemicalElement(name=, symbol=, atomicNumber=-1, atomicWeight=0.0, nobleMetal=null)
    

    我建议修改主构造函数,并为每个参数添加一个默认值:

    data class Activity(
        var updated_on: String = "",
        var tags: List<String> = emptyList(),
        var description: String = "",
        var user_id: List<Int> = emptyList(),
        var status_id: Int = -1,
        var title: String = "",
        var created_at: String = "",
        var data: HashMap<*, *> = hashMapOf<Any, Any>(),
        var id: Int = -1,
        var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
    ) 
    
    data class Item(var id: String = "",
                var title: String = "",
                var condition: String = "",
                var price: String = "",
                var categoryId: String = "",
                var make: String = "",
                var model: String = "",
                var year: String = "",
                var bodyStyle: String = "",
                var detail: String = "",
                var latitude: Double = 0.0,
                var longitude: Double = 0.0,
                var listImages: List<String> = emptyList(),
                var idSeller: String = "")
    
    data class Activity(
        var updated_on: String = "",
        var tags: List<String> = emptyList(),
        var description: String = "",
        var user_id: List<Int> = emptyList(),
        var status_id: Int = -1,
        var title: String = "",
        var created_at: String = "",
        var data: HashMap<*, *> = hashMapOf<Any, Any>(),
        var id: Int = -1,
        var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
    )
    
    一般来说,避免使用可为空的对象是一种很好的做法——以我们不需要使用它们的方式编写代码。与Java相比,不可空对象是Kotlin的优势之一。因此,上述第一个选项更可取

    这两个选项都将为您提供所需的结果:

    val activity = Activity()
    activity.title = "New Computer"
    sendToServer(activity)
    

    注意:在JVM上,如果主构造函数的所有参数 如果有默认值,编译器将生成一个额外的 将使用默认值的无参数构造函数。这 使Kotlin与Jackson或JPA等库一起使用变得更容易 通过无参数构造函数创建类实例的


    现代的答案应该是使用Kotlin的
    no-arg编译器插件
    ,它为经典的APIE创建了一个无参数的构造代码

    只需在build.gradle项目级别添加插件类路径即可

        dependencies {
        ....
    
        classpath "org.jetbrains.kotlin:kotlin-noarg:1.4.10"
    
        ....
        }
    
    然后配置注释以生成
    no arg
    构造函数

    apply plugin: "kotlin-noarg"
    
    noArg {
          annotation("your.path.to.annotaion.NoArg")
          invokeInitializers = true
    }
    
    然后定义注释文件
    NoArg.kt

     @Target(AnnotationTarget.CLASS)
     @Retention(AnnotationRetention.SOURCE)
     annotation class NoArg
    
    最后,在任何数据类中,您都可以简单地使用自己的注释

    @NoArg
    data class SomeClass( val datafield:Type , ...   )
    

    我曾经创建我自己的
    no arg
    构造函数作为接受的答案,我通过搜索得到了答案,但后来这个插件发布了,我发现它更干净了。

    谢谢@miensol,有没有办法用copy fun做到这一点。例如@SaiKiran要使用
    copy
    您需要一个数据类实例。要创建它,您需要调用一个构造函数——问题就在这里。我正在使用Kotlin 1.1.2 for Android Studio 2.3,emptyList不可用:/Nevermind。我没有将kotlin添加到build.gradle配置文件中。@Muhammadchhota
    emptyList
    不会重复分配内存。如果id是自动生成的,那么如何使用?对我来说很有用。对于Firebase聊天信息:
    类FeelComChatMessage(messageText:String=“”,messageUser:String=“”)
    @Panchal Amit谁自动生成id?房间?我认为你应该研究它的注释。最后一个注释是错误的。至少对于Gson序列化程序来说,事实上,Gson使用不安全机制来创建对象,并且它不会调用构造函数。我刚才在这里回答了一个相关的问题