05-属性引用
10.1.4 属性引用
和函数一样,类的成员属性也可以通过反射来获得。不过Kotlin的编译器在处理类属性时,会将其转换为get和set方法,而不是与属性同名的字段。代码如下。
package com.xzh
class User(){
var name:String="jack"
get() = field
set(v) {
field=v
}
}
将上面的User类编译为User.class字节码文件,然后使用javap命令反编译User.class文件后会看到如下代码。
public final class com.xzh.User {
public final java.lang.String getName();
public final void setName(java.lang.String);
public com.xzh.User();
}
可以发现,User类的name属性在编译后生成了getName和setName两个方法,这是Kotlin编译器处理属性特有的功能。如果要使用Java的反射技术来获取属性对象的值,则可以使用getMethod方法,但不能使用getField方法。代码如下。
fun main(args: Array<String>) {
val user = User()
var name = User::name
println(name.get(user))
name.set(user, "Tom")
println(name.get(user))
//编译报错无法通过getField来获取name属性的值
/*var field=User::class.java.getField("name")
field.set(user,"Mick")
println(field.get(user))*/
//使用getMethod和setMethod来动态设值和取值
var setName = User::class.java.getMethod("setName", java.lang.String().
javaClass)
setName.invoke(user, "John")
var getName = User::class.java.getMethod("getName")
println(getName.invoke(user))}
class User() {
var name: String = "jack"
get() = field
set(v) {
field = v
}
}
在上面的实例中,如果在Kotlin文件中使用getField方法来获取属性字段的值,则编译器会报错,因为在编译过程中,根本就没有生成对应字段。