對於任意一個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來決定是否
允許訪問字段,這樣就已經達到了封裝的目的了,
反射是一種特殊的方式,通常反射是給工具或者底層框架來事用的,在不知道實例的任何信息的情況下,獲取
特定字段的值。