Kt的构造方法重载的问题


#1
data class Model @JvmOverloads constructor(val id: Int = 1, val name: String, val age: Int)

我定义了一个 Model 类,并且第一个 id 字段有个默认属性值!

// 获取KClass
val modelClass = Model::class
//获取构造函数的个数
println("kt constructor size = ${modelClass.constructors.size}")

如上,我尝试通过反射创建一个 Model类的对象,但是我只能获取一个构造函数!并且这个构造函数式3个参数的!默认值的属性id,必须要传参数!

当然我也找到了解决办法,我通过添加 JvmOverloads 注解,然后通过 java的反射获取构造方法,然后能找到两个参数的构造方法!

但是想问下 kotlin 有没有提供更加好的方法?或者大佬们认为的更好的方法。


#2

当你用Java反射的时候能找到一个5个参数的构造器,你可以用这个


#3

能不能通过不加JvmOverloads实现呢?不用Java的反射


#4

能不能通过不加 JvmOverloads 实现呢?不用Java的反射


#5

找到使用kotlin,解决的方法了!

val firstConstructor = modelClass.constructors.first()
val secondParam = firstConstructor.parameters[1]
val thirdParam = firstConstructor.parameters[2]

val newModel2 = firstConstructor.callBy(mapOf(secondParam to "kotlin", thirdParam to 12))

使用 callBy 方法可以使用上默认参数!

参考自


#6

参考 代码 <<<<<< 点这里看源码 <<<<<<

data class KModel(val first: Int = 10, val name: String, val third: Int = 30, val forth: Int = 40)
//  注意 :  KModel::class 对应的是  KClass 对象, 里面构造方法数量为 1 , 代表只声明了一个方法
// 这里没有声明 @JvmOverloads , 所以生成class (注意对应的是 KModel::class.java 即java.reflect.Class对象)文件里只会有两个构造方法
// 方法1.  全部参数的构造方法
// 方法2.  全部参数 + 另外另外两个参数的构造方法 
//  KModel(Int, String, Int, Int, Int, DefaultConstructorMarker)
//    DefaultConstructorMarker 只是标示了倒数第二个参数, 转换为二进制后, 
//    来表示 , 第几个参数使用默认值
//    TODO 具体可以参考下面的例子 [tConstructor]

data class JavaModel @JvmOverloads constructor(val id: Int = 1, val name: String, val third: Int = 3)
// 这里声明 @JvmOverloads , 
// 所以生成class 文件里会包含所有可能的构造方法, 这里为4个构造方法


    fun tConstructor(): String {


        val sb = StringBuilder()

        val m0 = KModel(name = "1")
        //调用KModel 下注释 方法2 new KModel(0, "1", 0, 0, 13, null);
        // 13=1101 倒序查看第1,3,4位数字为1, 代表 第1, 3, 4 个参数没有传, 使用默认值

        val m11 = KModel(2, name = "1")
        //调用KModel 下注释 方法2 new KModel(2, "1", 0, 0, 12, null);
        // 12=1100 倒序查看第3,4位数字为1, 代表 第3, 4 个参数没有传, 使用默认值

        val m12 = KModel(name = "1", third = 3)
        //调用KModel 下注释 方法2 new KModel(0, "1", 3, 0, 9, null); 
        //9=1001 第1, 4 个参数没有传, 使用默认值

        val m13 = KModel(name = "1", forth = 4)
        //调用KModel 下注释 方法2 new KModel(0, "1", 0, 4, 5, null); 
        //5=0101 第1, 3 个参数没有传, 使用默认值

        val m21 = KModel(name = "1", third = 3, forth = 4)
        //调用KModel 下注释 方法2 new KModel(0, "1", 3, 4, 1, null); 
        //1=0001 第1个参数没有传, 使用默认值

        val m22 = KModel(2, name = "1", third = 3)
        //调用KModel 下注释 方法2 new KModel(2, "1", 3, 0, 8, null); 
        //8=1000 第4个参数没有传, 使用默认值

        val m23 = KModel(2, name = "1", forth = 4)
        //调用KModel 下注释 方法2 new KModel(2, "1", 0, 4, 4, null); 
        //4=0100 第3个参数没有传, 使用默认值

        val m3 = KModel(0, "", 1, 2)


        val size = KModel::class.constructors.size
        sb.appendln("Model:class.constructors.size = $size")
        for (c in KModel::class.constructors) {
            sb.appendln(c.toString())
        }
        val size2 = KModel::class.java.constructors.size
        sb.appendln("Model:class..javaconstructors.size = $size2")
        for (c in KModel::class.java.constructors) {
            sb.appendln(c.toString())
        }

        val size3 = JavaModel::class.constructors.size
        sb.appendln("Model:class.constructors.size = $size3")
        for (c in JavaModel::class.constructors) {
            sb.appendln(c.toString())
        }
        val size4 = JavaModel::class.java.constructors.size
        sb.appendln("Model:class..javaconstructors.size = $size4")
        for (c in JavaModel::class.java.constructors) {
            sb.appendln(c.toString())
        }

        return sb.toString()

    }

京ICP备16022265号-2 Kotlin China 2017 - 2018
本站由腾讯云提供计算服务