反射浅析

前言

记录反射的使用。方便后续的查询

什么是反射

反射英文单词 Reflection。在维基百科中定义

是指计算机程序在运行时(runtime)可以访问、检测和修改它本身状态或行为的一种能力

Java的反射是指程序在运行期可以拿到一个对象的所有信息

获取Class

1
val classApple = Apple::class.java
1
val classApple = Class.forName("com.allens.model_reflection.data.Apple")
1
var classApple = apple.javaClass

获取构造方法

1
2
3
4
5
//获取所有构造方法
//getDeclaredConstructors
classApple.declaredConstructors.forEach {
Log.i(TAG, it.toString())
}
1
2
3
4
5
//获取所有public类型的构造方法
//getConstructors
classApple.constructors.forEach {
Log.i(TAG, it.toString())
}
1
2
3
//获取某个带参数的构造方法
//getDeclaredConstructor
classApple.getDeclaredConstructor(Boolean::class.java)
1
2
3
//获取某个public类型的构造方法
//getConstructor
classApple.getConstructor(Boolean::class.java)

创建实例

1
2
//无参数实例
classApple.newInstance()
1
2
3
//有构造参数实例
classApple.getConstructor(Boolean::class.java, String::class.java)
.newInstance(false, "allens")

获取属性/属性值

获取对象的属性。可以知道属性是什么类型的。

1
2
3
4
5
//获取所有属性
//getDeclaredFields
classApple.declaredFields.forEach {
Log.i(TAG, it.toString())
}
1
2
3
4
5
//获取所有pubic类型的属性
//getFields
classApple.fields.forEach {
Log.i(TAG, it.toString())
}
1
2
3
//获取指定属性
//getDeclaredField
classApple.getDeclaredField("size")
1
2
3
4
//获取属性值
val apple = classApple.newInstance()
val filed = classApple.getDeclaredField("size")
var data = filed.get(apple)

获取方法

1
2
3
4
5
//获取所有方法
//getDeclaredMethods
classApple.declaredMethods.forEach {
Log.i(TAG, it.toString())
}
1
2
3
4
5
//获取所有public类型的方法
//getMethods
classApple.methods.forEach {
Log.i(TAG, it.toString())
}
1
2
3
//获取指定方法
//getDeclaredMethod
classApple.getDeclaredMethod("eatApple")
1
2
3
//指定public类型的方法 
//getMethod
classApple.getMethod("eatApple")

调用方法

1
2
3
//无参方法
val apple = classApple.newInstance()
val invoke = classApple.getDeclaredMethod("eatApple").invoke(apple)
1
2
3
4
5
//有参方法
val declaredMethod1 = classApple.getDeclaredMethod("getName", String::class.java)
declaredMethod1.isAccessible = true
val data1 = declaredMethod1.invoke(apple, "1234")
Log.e(TAG, "$data1")

反射的优缺点

优点:

  • 可以在一定程度上避免硬编码,提供灵活性和通用性
  • 可以在运行时像对待源代码语句一样动态解析字符串中可执行的代码

缺点:

  • 由于将部分信息检查工作从编译期推迟到了运行期,此举在提高了代码灵活性的同时,牺牲了一点点运行效率

参考

廖雪峰