对于属性的调用体现在两方面 (前提是要先获取这个属性)
一方面是获取这个属性的值(体现为get)
另一方面是给这个属性赋一个值(体现为set)
public class FieldTest {
@Test
public void test1() throws NoSuchFieldException, IllegalAccessException, InstantiationException {
Class clazz = Person.class;
//1.获取指定的属性(注意id在Person中声明的权限为public)
//注意,此方法要求运行时类中的属性声明为public
//因为属性一般不会声明为public,所以这种方法用的不多
Field id = clazz.getField("id");//给的参数是属性名
//非静态的属性要依托于对象才能设置值,所以要创建运行时类的对象
Object obj = clazz.newInstance();
Person p=(Person)obj;
//设置当前属性的值
//set(),参数1指明设置哪个对象的属性,参数2指明将此属性设置为多少
id.set(p,1001);//表示把p对象的id设置为1001(会自动装箱)
//获取当前某个对象的属性值,因为set的时候用的是Object,所以get的时候用的也是Object,但实际上是int
Object o = id.get(p);
int pId=(int)o;
System.out.println(pId);//1001
//如果一开始没有使用id.set(p,1001);那么输出的结果为0
//因为clazz.newInstance();调用空参构造器,使用的是默认值,所以输出结果为0
//age在Person中声明的为默认权限,如果把上面的程序中getField("id")改成getField("age"),运行会报异常
}
@Test
public void test2() throws IllegalAccessException, InstantiationException, NoSuchFieldException {
Class clazz = Person.class;
//1.创建运行时类的对象
Object obj = clazz.newInstance();
Person p=(Person)obj;
//2.getDeclaredField(String Filename),获取指定名字的属性,如果不存在会报异常
//name在Person类中声明为:private String name
Field name = clazz.getDeclaredField("name");
//name.set(p,"Tom");
//System.out.println(name.get(p));这么做会报非法访问异常IllegalAccessException:
//如果在Person类中改成public String name,就能够正确执行并输出Tom,但其他权限都会报异常
//这个时候是获取到了属性,但不能进行下面的set和get操作
//把set和get注释掉以后,正常执行
//解决方法如下
//3.保证当前属性是可访问的,public的属性虽然没有必要,但用这个方法也没有影响
name.setAccessible(true);//之后就可以进行修改了
//4.获取或设置指定对象的属性值
name.set(p,"Tom");
System.out.println(name.get(p));//Tom
}
}
如果想调用静态属性,set的第一个参数写当前运行时类.class,或者null即可,原因和调用运行时类的静态方法是一样的
如果是去get静态属性,get(null)即可