java反射——基础语法学习

2021-06-24  本文已影响0人  笑对浮华

写在前面:

反射技术在框架开发中举足轻重,可以说是框架设计的灵魂,现在市面上绝大部分的框架都用到了反射机制,其在程序的运行过程中,动态操作对象,解耦程序,提高程序扩展性,使得反射机制成为框架设计领域的神器,反射机制也是java进阶必不可少的知识。

下面是对java反射基础语法的学习和使用:

一、获取对象类型:

val name = "aaa"
val clazz = name.javaClass
print(clazz)

上面代码定义了一个字符串name,通过调用javaClass获取它的类型(java中调用getClass()方法),运行结果如下:

获取对象类型

当然了,这里定义的一个字符串,不用运行,我们也知道类型是String类型,这里只是举个简单的例子,由此我们可以延申,在日常开发中我们可以通过javaClass获取这个对象的类型。

二、获取对象构造方法:
为了便于测试,我定义了一个类:

    class Test(name: String,age: Int){
        private val sex: String? = null

        constructor(name: String) : this(name,0){
            "my name is $name".p("public constructor:")
        }

        private constructor(age: Int) : this("",age){
            "i am $age years old".p("private constructor:")
        }

        private fun introduce(name: String,age: Int){
            "my name is $name and i am $age years old".p("private method:")
        }
    }

其中重写了两个构造方法,一个公有的,一个私有的,还定义了一个私有方法和一个私有变量,后面会用到。.p()方法是一个打印扩展方法,如下:

    fun Any.p(tag: String){
        println("$tag -----> $this")
    }

回到正题,先把获取对象构造方法类型以及参数类型的代码贴上,跟着代码讲:

val test = Test("")
//获取test对象类型
val c2 = test.javaClass
c2.p("222")
//获取所有构造方法
val constructors = c2.declaredConstructors
constructors.forEach {
       //获取构造参数类型
       Modifier.toString(it.modifiers).p("构造函数类型:")
       val paramterTypes = it.parameterTypes
      //获取每个构造参数的每个参数类型
       paramterTypes.forEach { clazz ->
                "${clazz.name}  ".p("参数类型:")
       }
       "**********".p("")
}

这里直接new了一个Test对象是为了方便测试,在实际开发中可能是通过调用某个方法获得一个对象。接着通过javaClass获取对象类型,拿到对象类型后,通过declaredConstructors获取这个对象所有的构造方法,每个构造方法再通过modifiers可以获得当前构造方法的类型,是public还是private或者是protect就通过这个方法获取。通过parameterTypes可以获取构造参数类型。运行上述代码结果如下:

获取构造方法

第一行打印结果是new对象的时候调用了Test类的第一个构造方法生成的,第二行是test对象类型,后面是对每个构造方法的遍历打印,一共有三个构造方法,而类中我们只定义了两个,那是因为kotlin中直接将参数跟在类名后面会自动生成一个带所有参数的构造方法。通过对比代码和运行结果,也能验证通过declaredConstructors获取构造方法类型和parameterTypes获取构造参数类型的可行性。
上面是通过declaredConstructors获取所有的构造参数,除此之外还可以通过getDeclaredConstructor(Class<?> parameterTypes)获取特定的构造方法,传入你想要获取的那个构造放的构造参数类型,就可以获得相应的构造方法类型,比如想要获取Test类中定义的私有构造方法,代码如下:

val intConstructor = c2.getDeclaredConstructor(Int::class.java)
Modifier.toString(intConstructor.modifiers).p("constructor:")

打印结果:

获取特定的构造参数类型

走到这一步,在日常工作中貌似获取构造方法也没什么用,别急,获取构造方法在下一步中会用到。

三、获取对象实例:
上一步,我们通过declaredConstructors可以获取所有的构造方法,还可以通过getDeclaredConstructor(Class<?> parameterTypes)获取特定的构造方法,这一步我们通过特定的构造方法,获取对象实例,下面是获取实例的代码:

val stringConstructor = c2.getDeclaredConstructor(String::class.java)
stringConstructor.newInstance("张三")

val intConstructor = c2.getDeclaredConstructor(Int::class.java)
//私有构造方法需要设置这一步
intConstructor.isAccessible = true
intConstructor.newInstance(25)

获取到的构造方法通过newInstance(Object ... initargs)方法获得对象实例,传入的值就是构造参数值。这里需要注意的是,私有构造方法需要设置isAccessible = true才可以。下面看下打印结果:

获取实例

四、调用私有方法:
上面是获取构造方法的过程,这一步我们通过对象类型获取类中的私有方法,干货来了。

val method = c2.getDeclaredMethod("introduce",String::class.java,Int::class.java)
method.isAccessible = true
method.invoke(test,"李四",26)

通过getDeclaredMethod(String name, Class<?>... parameterTypes)获取私有方法,第一个参数是你想要获取的方法名,后面传入调用这个方法需要的参数类型。由于是私有方法,所以需要设置isAccessible = true。最后通过invoke() 方法传入反射的对象,第一个参数这里直接传入new出来的test对象,在实际开发中可用newInstance()获得的实例,后面的参数就是私有方法的传参。参数等就实现了私有方法的调用。下面是运行结果:

调用私有方法

五、调用私有变量:
私有方法的调用攻破了,私有变量自然跑不掉,下面是设置私有变量值的代码:

val declaredField = c2.getDeclaredField("sex")
declaredField.isAccessible = true
declaredField.set(test,"女")
declaredField.get(test).p("sex:")

通过getDeclaredField(String name)传入变量名获取私有变量,私有属性需要设置isAccessible = true,之后通过set(Object obj, Object value)设置变量值,第一个参数是反射的对象,第二个参数就是你要设置的值,最后可以通过get(Object obj)方法获取私有变量值。看下运行结果:

设置私有变量值

以上五步就是对java反射基础语法的一个学习和简单运用,从第一步到第五步基本是环环相扣的。下面总结一下:

1、通过javaClass获取对象类型;
2、通过对象类型调用getDeclaredConstructor()获取特定的构造方法;
3、通过构造方法调用newInstance()可以获得对象实例;
4、通过对象类型调用getDeclaredMethod()获取私有方法,将获取到的实例传入invoke()方法可以完成对私有方法的调用;
5、调用getDeclaredField()获取私有变量,将获取到的实例传入可以完成对私有变量值的设置。

以上就是对反射技术的一个学习总结,谢谢阅读。

上一篇下一篇

猜你喜欢

热点阅读