1、類的加載
一般來說,java程序在主動使用某個類時,若該類沒有加載到內存中,JVM會通過加載,連接,初始化三個階段對該類進行初始化。類加載到系統後就是一個java.lang.Class對象,例如:
我有一個Person類,該類沒有在內存中,當我執行:Person p = new Person();時,類加載器會將Person類加載到系統,並持有一個Class對象。
類加載器通常不會等到詩詞使用某個類時才加載該類,java虛擬機一般會預先加載某些類在內存中,比如我們常用的系統工具類,String,Map,等工具類都是預先加載的。
2、獲得Class對象
通常有如下三種方式:1)使用Class類的forName(String clazzName)靜態方法。這裏的clazz必須的完整路徑,比如:com.test.Person
2)調用某個類的class屬性來獲得該類的Class對象。例如: Class clazz = Person.class;
3)調用某個對象的getClass方法。例如:
Person p = new Person();
Class clazz = p.getClass();
3、通過反射操作對象
1)先創建com.test.Person類:public class Person {
private String name = "gonjan";
private Integer age = 24;
public void print() {
System.out.println("name:" + name + " age:" + age);
}
public void say(String content) {
System.out.println(name + " say :" + content);
}
private void privateSay(String content) {
System.out.println(name + "say :" + content);
}
}
2)當獲得某個類對應的Class對象後,就可通過該Class對象來獲取該類的全部或指定方法,全部或指定成員變量。
獲得Class對象1:
Class clazz = Class.forName("com.test.Person");
獲得Class對象2:
Person p1 = new Person();
Class clazz = Person.class;
獲得Class對象3:
Person p1 = new Person();
Class clazz = p1.getClass();
通過class對象獲得Person中所有的方法:
Method[] methods = clazz.getMethods();
通過class對象獲得對象方法,並調用
Method mt = clazz.getMethod("say", String.class);
mt.invoke(p1, "通過反射調用對象public方法!");
通過反射獲得類中的私有方法,並可以通過setAccessible來取消其私有權限(ps:單例模式中,可以通過這方式打破私有構造方法保證只有一個對象)
Method mt2 = clazz.getDeclaredMethod("privateSay", String.class);
mt2.setAccessible(true); //取消了privaeSay方法的private權限
mt2.invoke(p1, "通過反射調用對象private方法!");//通過invoke方法來調用類中的方法
通過Filed中的方法使類中私有成員變量可見。
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(p1, 30);//這裏可以直接更改p中的私有成員變量