在Android中会有一些异常方法或者属性,是你想用而拿不到的,这种时候你就需要使用反射了,反射不能跨进程使用
反射机制:(官方解释)
- 在运行状态中,对于任意一个类或者任意一个对象,都能够知道这个类的所有属性和方法,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
反射原理:(以下仅是我个人理解,如有误请帮忙指正,谢谢)
- java中的类运行后JVM会在本地生成一个class文件,而反射则是去加载这个文件,读取里面的信息,解析里面的代码
反射的简单应用
首先我在本地新建了一个类TestFanshe.java,里面只有一个方法
public String getString(String s){
return s + "码农";
}
然后我再用反射的方法去拿到类对象,然后通过反射的方法调用类里面的方法,拿到返回值
Class<?> aClass = null;
try {
aClass = Class.forName("com.weidu.plugincityassistant.TestFanshe");
Object o1 = ReflexUtils.setMethod(aClass.newInstance(),"getString", false, "我是一个");
Log.i("test_fanshe","o1 = " + o1.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
最后的打印结果为 “我是一个码农”
这段代码中,首先是通过Class.forName()方法,传入所需要的这个类的全类名(全类名是这个类的包名加上类名),返回类对象aClass,然后通过setMethod方法调用了这个类的方法并拿到返回值o1,这个值是object类型的,需要强转为string类型,再来解析setMethod方法
public <T> T setMethod(Object obj, String method, boolean isObject, Object ... vlaue){
return setMethod(obj, obj.getClass(), method, isObject, vlaue);
}
/**
*
* @param obj 对象
* @param cls 对象class
* @param method 方法名
* @param isObj 是否执行到Objcet
* @param vlaue 方法参数
* @param <T>
* @return
*/
public <T> T setMethod(Object obj, Class cls, String method, boolean isObject, Object ... vlaue){
try {
Class[] classes = new Class[vlaue.length];
for (int i = 0; i < vlaue.length; i++) {
classes[i] = vlaue[i] == null ? Object.class : vlaue[i].getClass();
}
Method m = cls.getDeclaredMethod(method, classes);
m.setAccessible(true);
return (T) m.invoke(obj, vlaue);
} catch (NoSuchMethodException e) {
if (cls.getSuperclass() != null && (isObject || cls.getSuperclass() != Object.class)){
return setMethod(obj, cls.getSuperclass(), method, isObject, vlaue);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
这里面 每个参数的意思上面都有就不一一解说了,通过这样,我们就可以实现通过反射的形式拿到类并调用里面的方法了
附上反射的三种实现方式
- 通过全类名
Class<?> aClass = Class.forName("packagename.TestFanshe");
- 指定类型的class对象
Class<?> cls=TestFanshe.Class();
TestFanshe t =(TestFanshe)cls.newInstance();
- 通过getClass()方式
TestFanshe test = new TestFanshe();
Class<?> cls=test .getClass();
TestFanshe test2=(TestFanshe)cls.newInstance();
三种方式个人推荐优选第一种,当你当前都拿不到这个类但是知道这个类的全类名的时候,二三种就起不到作用了
关于Class<?> cls=Class.forName("fanshe.Person");
cls内部有哪些方法供我们使用
好了,反射就讲解这些了,如有更多见解的,请在下方留言,互相学习