我能抽象出整个世界...
但是我却不能抽象出你...
你肯定是一个单例,因为你是那样的独一无二...
所以我的世界并不完整...
我可以重载甚至覆盖这个世界里的任何一种方法...
但是却不能覆盖对你的思念...
也许命中注定了,你与我存在于不同的包里...
在你的世界里,你被烙上了私有的属性...
我用尽全身力气,也找不到访问你的接口...
# 我不愿就此甘心,找到了藏身神殿的巫师,教会了我穿越时空的方法...
# 终于,我用反射这把利剑,打开了你空间的缺口...
# 并发现了接近你的秘密...
当我迫不及待地调用了爱你这个方法...
并义无返顾的把自己作为参数传进这个方法时...
我才发现爱上你是一个没有终止条件的递归...
它不停的返回我对你的思念并压入我心里的堆栈...
在这无尽的黑夜中 ,终于体验到你对我爱的回调...
我的内存里已经再也装不下别人...
当我以为将与你在这个死循环中天荒地老时...
万恶的系统抛出了爱的异常...
此刻我才发现,我不过是操纵于虚拟机下的一个线程,你也是...
但我毫不后悔,因为在爱的洗礼之后...
我看见了一个新的生命,那是我们的, 继承 ...
我们的继承越来越多,他们的风格都是多态的...
这使得我们在别人面前可以风光无限
今天在地铁上看见了这段话,其中有几句话(#部分),令我无比动容,对于我们敲代码的人来说,代码无疑是我的爱人,是我的知己,然而,对于爱人知己的私密部分我们总是喜欢窥视,因为爱一个必须了解一个人。哈哈,所以,反射这把利剑就是我们通往隐秘部分的阶梯、是通道、是表达爱的方式。好了,地铁上也不好码字,正式介绍反射。
一、反射
Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。)语言的一个关键性质。(来源网络)
1.1 反射作用
反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。那么我们便可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等等;但是需要注意的是反射使用不当会造成很高的资源消耗(来源网络) 先上一个在开发中常用的反射工具类,细节部分1.2介绍,看不看无所谓哈
object RefInvoke {
//无参
fun createObject(className: String?): Any? {
val pareTyples = arrayOf<Class<*>>()
val pareVaules = arrayOf<Any>()
try {
val r = Class.forName(className)
return createObject(r, pareTyples, pareVaules)
} catch (e: ClassNotFoundException) {
e.printStackTrace()
}
return null
}
//无参
fun createObject(clazz: Class<*>): Any? {
val pareTyple = arrayOf<Class<*>>()
val pareVaules = arrayOf<Any>()
return createObject(clazz, pareTyple, pareVaules)
}
//一个参数
fun createObject(className: String?, pareTyple: Class<*>, pareVaule: Any): Any? {
val pareTyples = arrayOf(pareTyple)
val pareVaules = arrayOf(pareVaule)
try {
val r = Class.forName(className)
return createObject(r, pareTyples, pareVaules)
} catch (e: ClassNotFoundException) {
e.printStackTrace()
}
return null
}
//一个参数
fun createObject(clazz: Class<*>, pareTyple: Class<*>, pareVaule: Any): Any? {
val pareTyples = arrayOf(pareTyple)
val pareVaules = arrayOf(pareVaule)
return createObject(clazz, pareTyples, pareVaules)
}
//多个参数
fun createObject(
className: String?,
pareTyples: Array<Class<*>>,
pareVaules: Array<Any>?
): Any? {
try {
val r = Class.forName(className)
return createObject(r, pareTyples, pareVaules)
} catch (e: ClassNotFoundException) {
e.printStackTrace()
}
return null
}
//多个参数
fun createObject(clazz: Class<*>, pareTyples: Array<Class<*>>, pareVaules: Array<Any>?): Any? {
try {
val ctor = clazz.getDeclaredConstructor(*pareTyples)
ctor.isAccessible = true
return ctor.newInstance(pareVaules)
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
//多个参数
fun invokeInstanceMethod(
obj: Any?,
methodName: String?,
pareTyples: Array<Class<*>>,
pareVaules: Array<Any>?
): Any? {
if (obj == null) return null
try {
//调用一个private方法
val method: Method =
obj.javaClass.getDeclaredMethod(methodName, *pareTyples) //在指定类中获取指定的方法
method.setAccessible(true)
return method.invoke(obj, pareVaules)
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
//一个参数
fun invokeInstanceMethod(
obj: Any?,
methodName: String?,
pareTyple: Class<*>,
pareVaule: Any
): Any? {
val pareTyples = arrayOf(pareTyple)
val pareVaules = arrayOf(pareVaule)
return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules)
}
//无参
fun invokeInstanceMethod(obj: Any?, methodName: String?): Any? {
val pareTyples = arrayOf<Class<*>>()
val pareVaules = arrayOf<Any>()
return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules)
}
//无参
fun invokeStaticMethod(className: String?, method_name: String?): Any? {
val pareTyples = arrayOf<Class<*>>()
val pareVaules = arrayOf<Any>()
return invokeStaticMethod(className, method_name, pareTyples, pareVaules)
}
//一个参数
fun invokeStaticMethod(
className: String?,
method_name: String?,
pareTyple: Class<*>,
pareVaule: Any
): Any? {
val pareTyples = arrayOf(pareTyple)
val pareVaules = arrayOf(pareVaule)
return invokeStaticMethod(className, method_name, pareTyples, pareVaules)
}
//多个参数
fun invokeStaticMethod(
className: String?,
method_name: String?,
pareTyples: Array<Class<*>>,
pareVaules: Array<Any>?
): Any? {
try {
val obj_class = Class.forName(className)
return invokeStaticMethod(obj_class, method_name, pareTyples, pareVaules)
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
//无参
fun invokeStaticMethod(clazz: Class<*>, method_name: String?): Any? {
val pareTyples = arrayOf<Class<*>>()
val pareVaules = arrayOf<Any>()
return invokeStaticMethod(clazz, method_name, pareTyples, pareVaules)
}
//一个参数
fun invokeStaticMethod(
clazz: Class<*>,
method_name: String?,
classType: Class<*>,
pareVaule: Any
): Any? {
val classTypes = arrayOf(classType)
val pareVaules = arrayOf(pareVaule)
return invokeStaticMethod(clazz, method_name, classTypes, pareVaules)
}
//多个参数
fun invokeStaticMethod(
clazz: Class<*>,
method_name: String?,
pareTyples: Array<Class<*>>,
pareVaules: Array<Any>?
): Any? {
try {
val method: Method = clazz.getDeclaredMethod(method_name, *pareTyples)
method.setAccessible(true)
return method.invoke(null, pareVaules)
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
//简写版本
fun getFieldObject(obj: Any, filedName: String?): Any? {
return getFieldObject(obj.javaClass, obj, filedName)
}
fun getFieldObject(className: String?, obj: Any?, filedName: String?): Any? {
try {
val obj_class = Class.forName(className)
return getFieldObject(obj_class, obj, filedName)
} catch (e: ClassNotFoundException) {
e.printStackTrace()
}
return null
}
fun getFieldObject(clazz: Class<*>, obj: Any?, filedName: String?): Any? {
try {
val field: Field = clazz.getDeclaredField(filedName)
field.isAccessible = true
return field.get(obj)
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
//简写版本
fun setFieldObject(obj: Any, filedName: String?, filedVaule: Any?) {
setFieldObject(obj.javaClass, obj, filedName, filedVaule)
}
fun setFieldObject(clazz: Class<*>, obj: Any?, filedName: String?, filedVaule: Any?) {
try {
val field: Field = clazz.getDeclaredField(filedName)
field.setAccessible(true)
field.set(obj, filedVaule)
} catch (e: Exception) {
e.printStackTrace()
}
}
fun setFieldObject(className: String?, obj: Any?, filedName: String?, filedVaule: Any?) {
try {
val obj_class = Class.forName(className)
setFieldObject(obj_class, obj, filedName, filedVaule)
} catch (e: ClassNotFoundException) {
e.printStackTrace()
}
}
fun getStaticFieldObject(className: String?, filedName: String?): Any? {
return getFieldObject(className, null, filedName)
}
fun getStaticFieldObject(clazz: Class<*>, filedName: String?): Any? {
return getFieldObject(clazz, null, filedName)
}
fun setStaticFieldObject(classname: String?, filedName: String?, filedVaule: Any?) {
setFieldObject(classname, null, filedName, filedVaule)
}
fun setStaticFieldObject(clazz: Class<*>, filedName: String?, filedVaule: Any?) {
setFieldObject(clazz, null, filedName, filedVaule)
}
}
1.2 反射技术
- 根据一个字符串得到一个类的对象。
- 获取一个类的所有公用或私有、静态或实例的字段、方法、属性。
- 对泛型类的反射。
1.2.1 根据一个字符串得到一个类
得到一个类或者属性是我们在使用动态代理的时候大量的用作参数,所以必须要知道的
- getClass
String str = "123";
Class clazz = str.getClass();
- Class.forName()
在开发中使用比较多
try {
Class<?> aClass = Class.forName("");
// 获取父类对象
Object o = aClass.getSuperclass();
} catch (Exception e) {
e.printStackTrace();
}
- Class 属性
每个类都有class 属性,通过class 属性可以得到类的类型
Class<String> stringClass = String.class;
Class<Integer> integerClass = int.class;
- TYPE 属性
基本数据类型都有自己的TYPE 属性 本质上是返回一个Class 对象
/*
* Return the runtime's Class object for the named
* primitive type.
*/
@FastNative
static native Class<?> getPrimitiveClass(String name);getPrimitiveClass
属性的TYPE
Class<Boolean> type = Boolean.TYPE;
Class<Double> doubleClass = Double.TYPE;
1.2.2 获取类成员
在1.2.1 中获取到了一个类,那在现实开发中,类的成员才是我们真正操作的东西
- 获取类的构造函数
获取类的构造函数包含两种类型,即有参、无参。获取方法有两种,即public、private 演示类
/**
* @author: kpa
* @time: 2021/4/21
* @email: billkp@yeah.net
**/
public class Test {
private String name;
public Test(String name) {
this.name = name;
}
public Test() {
}
private Test(String name, String args1) {
}
}
- 获取类的所有构造函数
Test test = new Test();
Class<? extends Test> testClass = test.getClass();
// getDeclaredConstructors 获取所有的构造方法
Constructor<?>[] constructors = testClass.getDeclaredConstructors();
- 获取类的某个构造函数
Constructor<? extends Test> declare = testClass.getDeclaredConstructor();
//获取有参数的构造函数
Class<String> aClass = String.class;
Constructor<? extends Test> declare = testClass.getDeclaredConstructor(aClass);
// 私有构造函数 并调用
Class[] params = {String.class, String.class};
Constructor<? extends Test> constructor = testClass.getDeclaredConstructor(params);
try {
Object instance = constructor.newInstance("kpa", "test");
} catch (Exception e) {
e.printStackTrace();
}
- 调用构造函数
Class<?> aClass = Class.forName("");
// 调用构造函数,获取类的实例
Object o1 = aClass.newInstance();
- 获取类的方法
根据上面获取构造函数的方式,通过getXXX ,就可以得到自己想要的方法,getMethodX相关
try {
// 获取私有方法并且调用改方法
Object instance = constructor.newInstance("kpa", "test");
Class p = String.class;
Method method = testClass.getDeclaredMethod("test", p);
method.setAccessible(true);
Object value = "我是谁?";
method.invoke(instance, value);
} catch (Exception e) {
e.printStackTrace();
}
- 获取类的字段
根据上面的经验,获取字段肯定是get Field相关的方法,自己试一下就知道了
1.2.3 对泛型类的反射
示例类:
这个代码不仅有反射,还是一个单例
public abstract class Test1<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
对于单例,我们知道的他的对象是唯一的,那我们肯定不能再进行newInstance了
try {
// 取出单例中的mInstance 就拿到了单例的对象 注意Class<?>
Class<?> aClass1 = Class.forName("");
Field mInstance = aClass1.getDeclaredField("mInstance");
mInstance.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}