通过Class对象的getField(String name)或getFields()可以获得指定的或者全部的public成员变量;而通过getDeclaredField(String name)或getDeclaredFields()可以获得指定的或者全部的成员变量,与成员变量的访问权限无关。
Field提供了如下了如下两个方法来读取或设置成员变量:
(a)getXxx(Object obj):获取obj对象的该成员变量的值,此处Xxx对应8中基本类型,如果该成员变量的类型是引用类型,则取消get后面的Xxx。
(b)setXxx(Object obj , Xxx val):将obj对象的该成员变量设置为val值,此处Xxx对应8种基本类型,如果该成员变量的类型是引用类型,则取消set后面的Xxx。
例子1(通过反射修改成员变量):
public class Person
{
private String name;
private int age;
@Override
public String toString()
{
return "Person [ name: " + name + " , age: " + age + " ]";
}
}
下面通过反射来修改Person对象的成员变量的值:
private void showPerson()
{
try
{
Class<?> clazz = Class.forName("com.test.zhangtao.activitytest.Person");
Object p = clazz.newInstance();
//修改name属性
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(p , "Jack");
//修改age属性
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true);
ageField.setInt(p , 30);
Log.d(TAG , p.toString());
}
catch (Exception e)
{
e.printStackTrace();
}
}
还有下面一种方式:
private void showPerson()
{
try
{
Person p = new Person();
Class<Person> clazz = Person.class;
//修改name属性
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(p , "Jack");
//修改age属性
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true);
ageField.setInt(p , 30);
Log.d(TAG , p.toString());
}
catch (Exception e)
{
e.printStackTrace();
}
}
还有下面一种方式:
private void showPerson()
{
try
{
Person p = new Person();
Class<?> clazz = p.getClass();
//修改name属性
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(p , "Jack");
//修改age属性
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true);
ageField.setInt(p , 30);
Log.d(TAG , p.toString());
}
catch (Exception e)
{
e.printStackTrace();
}
}
例子2(通过反射获取状态栏的高度)
protected int getStatusBarHeight()
{
try
{
Class<?> c = Class.forName("com.android.internal.R$dimen");
Object obj = c.newInstance();
Field field = c.getField("status_bar_height");
int x = Integer.parseInt(field.get(obj).toString());
return getResources().getDimensionPixelSize(x);
}
catch (Exception e)
{
e.printStackTrace();
}
return 0;
}
-2-获取某个对象的pulic修饰的实例变量的值的通用方法
public Object getProperty(Object owner, String fieldName) throws Exception
{
Class ownerClass = owner.getClass();
Field field = ownerClass.getField(fieldName);
Object property = field.get(owner);
return property;
}
-3-获取某个类的pulic修饰的类变量的值的通用方法
public Object getStaticProperty(String className, String fieldName) throws Exception
{
Class ownerClass = Class.forName(className);
Field field = ownerClass.getField(fieldName);
Object property = field.get(ownerClass);
return property;
}
这里和上面有些不同,因为该属性是静态的,所以直接从类的Class里取。
-4-反射在Android中的应用
在ViewConfiguration这个类中有一个叫做sHasPermanentMenuKey的静态变量,系统就是根据这个变量的值来判断手机有没有物理Menu键的。当然这是一个内部变量,我们无法直接访问它,但是可以通过反射的方式修改它的值,让它永远为false就可以了。
private void setOverflowShowingAlways()
{
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
catch (Exception e)
{
e.printStackTrace();
}
}