Kotlin学习

Kotlin之反射

2019-04-26  本文已影响0人  心随你咚

Class对象:

Class对象是将class文件文件读入内存,并为之创建一个Class对象。类加载器首先会检查这个类的Class对象是否已被加载过,如果尚未加载,默认的类加载器就会根据类名查找对应的.class文件。获取Class对象的有三种方式:(1)直接通过对象来获取;(2)通过Class.forName来获取;(3)通过类直接获取。经常用到第二种方式,因为第一种和第三种都需要导入这个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")
    // 直接通过对象来获取(需要需要导入这个类的包,并且有实例对象)
    val clazz1 = password.javaClass
    // 通过Class.forName来获取(需要知道类的路径)
    val clazz2 = Class.forName("com.example.kotlinstudy.reflect.Password")
    // 通过类直接获取(需要导入这个类的包)
    val clazz3 = Password::class.java

反射的一些实际应用:

  1. 修改类中私有属性字段的值
    我们现在获取到一个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)

输出结果:

 : 123 : RSA : 654312

备注:Class中有getField(fieldname)方法只能获取Public的字段Field。这里我们用getDeclaredField(fieldname)方法可以获取所有的字段Field。

  1. 调用类中私有属性的方法
    // 模拟获取到一个Password类的实例
    val password = Password("123")

    // 直接通过对象来获取
    val clazz1 = password.javaClass
    val method = clazz1.getDeclaredMethod("getKey")
    method.isAccessible = true
    method.invoke(password)

输出结果:

getKey RSA123456

调用setKey方法,反射带参数的方法

    // 模拟获取到一个Password类的实例
    val password = Password("123")

    // 直接通过对象来获取
    val clazz1 = password.javaClass
    val method = clazz1.getDeclaredMethod("setKey", String::class.java)
    method.isAccessible = true
    method.invoke(password, "111111")

输出结果:

setKey : 111111
  1. 对过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)

输出结果:

 : 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是设置的值
field.set(obj: Object, value: Object)

Method对象的方法

// obj是Class对象的实例,agrs是对应方法的参数
method.invoke(obj: Object, Object... args)
上一篇 下一篇

猜你喜欢

热点阅读