对于任意一个object实例,只要我们获取了它的class,就能得到它的一切信息。
Class类听过了几个方法获取字段:
Field getField(name):根据字段名获取某个public的field(包括父类的public 字段)
Filed getDeckaredField(name):根据字段名获取当前类的某个field(不包括父类)
Field[] getFields():获取所有的public 的field(包括父类)
Filed[] getDeclaredFields():获取当前类的所有field(不包括父类)
获取字段的值:
先获取Class实例,在获取Field实例,再用Field.get(Object)获取指定实例的指定字段的值:
package reflaction;
import java.lang.reflect.Field;
public class demo1 {
public static void main(String[] argsl) throws Exception {
Class stdClass = Student.class;
System.out.println(stdClass.getField("score"));
//System.out.println(stdClass.getField("name"));
System.out.println(stdClass.getDeclaredField("grade"));
Object p = new Person1("xiao ming");
Class c = p.getClass();
Field f = c.getDeclaredField("name");
f.setAccessible(true);
Object value = f.get(p);
System.out.println(value);
}
}
class Person1 {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person1() {
}
public Person1(String name) {
this.name = name;
}
}
class Student extends Person1 {
public int score;
private int grade;
Student() {
super();
}
Student(String name) {
super.setName(name);
}
}
写代码过程遇到的问题就是private属性,正常情况下Main类是无法访问的,例如代码中的name属性,
这里会出现一个IllegalAccessException,解决这个问题,我们可以把name属性设置为public或者是在
调用Object value=f.get(p)之前增加一个设置
f.setAccessible(true);
这个设置的意思就是不管这个字段是不是public,一律允许访问,
setAccessible(true)有可能会失败,如果JVM运行期存在SecurityManager,这个就会根据规则进行检查,有可能会
阻止
setAccessible(true),例如某个SecurityManager可能不允许对java和javax开头的package的类调用setAccessible(true),
这样可以保证JVM核心库的安全。
问题:如果可以通过反射获取private 字段,那么类的封装还有什么意义?
正常情况下,我们是通过类的实例来访问字段的,编译器会根据public protected,private来决定是否
允许访问字段,这样就已经达到了封装的目的了,
反射是一种特殊的方式,通常反射是给工具或者底层框架来事用的,在不知道实例的任何信息的情况下,获取
特定字段的值。