Class對象:
Class對象是將class文件文件讀入內(nèi)存,并為之創(chuàng)建一個Class對象。類加載器首先會檢查這個類的Class對象是否已被加載過,如果尚未加載,默認的類加載器就會根據(jù)類名查找對應(yīng)的.class文件。獲取Class對象的有三種方式:(1)直接通過對象來獲取;(2)通過Class.forName來獲?。?3)通過類直接獲取。經(jīng)常用到第二種方式,因為第一種和第三種都需要導(dǎo)入這個Class對象的包才可以用。第二種方式則不需要。代碼如下
(這里新建一個密碼類,方便演示)
package com.example.kotlinstudy.reflect
class Password constructor(password: String) {
private var strName : String = ""
private var strPassword: String = password
private val strKey = "123456"
val type = "RSA"
constructor(password: String, name: String) : this(password){
strName = name
}
private fun getKey() : String{
println("getKey $type$strKey")
return type + strKey
}
override fun toString(): String {
return "$strName : $strPassword : $type"
}
}
三種方式
val password = Password("123")
// 直接通過對象來獲?。ㄐ枰枰獙?dǎo)入這個類的包,并且有實例對象)
val clazz1 = password.javaClass
// 通過Class.forName來獲?。ㄐ枰李惖穆窂剑? val clazz2 = Class.forName("com.example.kotlinstudy.reflect.Password")
// 通過類直接獲取(需要導(dǎo)入這個類的包)
val clazz3 = Password::class.java
反射的一些實際應(yīng)用:
- 修改類中私有屬性字段的值
我們現(xiàn)在獲取到一個Password對象,但是需要改變其私有變量strKey的值,從聲明來看Password并未提供setter方法。這個時候,反射就可以幫上忙
// 模擬獲取到一個Password類的實例
val password = Password("123")
// 直接通過對象來獲取
val clazz1 = password.javaClass
val field = clazz1.getDeclaredField("strKey")
field.isAccessible = true
field.set(password, "654312")
println(password)
輸出結(jié)果:
: 123 : RSA : 654312
備注:Class中有g(shù)etField(fieldname)方法只能獲取Public的字段Field。這里我們用getDeclaredField(fieldname)方法可以獲取所有的字段Field。
- 調(diào)用類中私有屬性的方法
// 模擬獲取到一個Password類的實例
val password = Password("123")
// 直接通過對象來獲取
val clazz1 = password.javaClass
val method = clazz1.getDeclaredMethod("getKey")
method.isAccessible = true
method.invoke(password)
輸出結(jié)果:
getKey RSA123456
調(diào)用setKey方法,反射帶參數(shù)的方法
// 模擬獲取到一個Password類的實例
val password = Password("123")
// 直接通過對象來獲取
val clazz1 = password.javaClass
val method = clazz1.getDeclaredMethod("setKey", String::class.java)
method.isAccessible = true
method.invoke(password, "111111")
輸出結(jié)果:
setKey : 111111
- 對過Class對象new一個實例
// 通過Class.forName來獲取
val clazz2 = Class.forName("com.example.kotlinstudy.reflect.Password")
var obj = clazz2.getConstructor(String::class.java).newInstance("147")
println(obj)
obj = clazz2.getConstructor(String::class.java, String::class.java).newInstance("147", "kotlin")
println(obj)
輸出結(jié)果:
: 147 : RSA : 123456
kotlin : 147 : RSA : 123456
知識梳理
Class對象的方法:
// 獲取所有公有方法
public Method[] getMethods()
// 獲取某個公有方法
public Method getMethod(methodname: String)
// 獲取所有的成員方法(包括私有)
public Method[] getDeclaredMehods()
// 獲取某個成員方法(包括私有)
public Method getDeclaredMehod(methodname: String)
// 獲取所有公有字段
public Field[] getFields()
// 獲取某個公有字段
public Field getField(fieldname: String)
// 獲取所有的字段(包括私有)
public Field[] getDeclaredFields()
// 獲取某個字段(包括私有)
public Field getDeclaredField(fieldname: String)
Field對象的方法:
// obj是Class對象的實例,value是設(shè)置的值
field.set(obj: Object, value: Object)
Method對象的方法
// obj是Class對象的實例,agrs是對應(yīng)方法的參數(shù)
method.invoke(obj: Object, Object... args)