原理
用反射你几乎可以做任何事情。Class对象的由来是将class文件读入内存,并为之创建一个Class对象。利用这个Class对象,你可以实现反射的功能。
对于Field的get和set。
最底层无非是计算偏移量,调用
sun.misc.Unsafe#getInt(java.lang.Object, long)
来获取变量值。
核心的类是FieldAccessor。
对于利用反射调用方法。底层对应的是
private static native Object invoke0(Method var0, Object var1, Object[] var2);
//var1是一个method对象
NativeMethodAccessorImpl var2 = new NativeMethodAccessorImpl(var1);
DelegatingMethodAccessorImpl var3 = new DelegatingMethodAccessorImpl(var2);
var2.setParent(var3);
return var3;
在构造完成DelegatingMethodAccessorImpl后,将其放在method对象的methodAccessor字段中。
注意事项
这里要注意一件非常tricky的事情。下面的代码是无法正常运行的
s.getClass().getDeclaredFields()[3].setAccessible(true);
try {
String gdl = (s.getClass().getDeclaredFields()[3].get(s).toString());
System.out.println(field.get(s).toString());
}catch (Exception e){
e.printStackTrace();
}
System.out.println(GsonUtils.toJson(s));
要改成
Field field = s.getClass().getDeclaredFields()[3];
field.setAccessible(true);
try {
String gdl = field.get(s).toString();
System.out.println(field.get(s).toString());
}catch (Exception e){
e.printStackTrace();
}
System.out.println(GsonUtils.toJson(s));
这是因为每次获取的field对象都是拷贝出来的不同对象。可以看下Field类copy方法的执行方式。
Field copy() {
// This routine enables sharing of FieldAccessor objects
// among Field objects which refer to the same underlying
// method in the VM. (All of this contortion is only necessary
// because of the "accessibility" bit in AccessibleObject,
// which implicitly requires that new java.lang.reflect
// objects be fabricated for each reflective call on Class
// objects.)
if (this.root != null)
throw new IllegalArgumentException("Can not copy a non-root Field");
Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations);
res.root = this;
// Might as well eagerly propagate this if already present
res.fieldAccessor = fieldAccessor;
res.overrideFieldAccessor = overrideFieldAccessor;
return res;
}