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中的私有成员变量