0- 一个类被类加载器加载到JVM(内存)中后,生成了多个对象:Class Constructor Method Field
1- 三种创建字节码文件对象
* a:Object类的getClass()方法,判断两个对象是否是同一个字节码文件
* b:静态属性class,锁对象
* c:Class类中静态方法forName(),读取配置文件
2- 通过字节码文件对象创建该类对象
(通过反射获取带参构造方法并使用)
*a: newInstance()
*b: Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了,可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance("张三",20)方法创建对象
Class clazz = Class.forName("com.th.reflect.Person");
Constructor[] constructors = clazz.getConstructors();//获取所有的构造方法
Constructor constructor = clazz.getConstructor(Class.String, Class.Integer);//获取固定的有参构造
3- 通过反射获取私有成员变量并使用
其中使用到的类:
Class : 获取到字节码文件对象;
forName();
getConstructor();
getField("xxx"); //只能获取公有的字段
getDeclaredField("xxx"); //暴力获取私有字段
Constructor:通过字节码对象获取到构造方法;
newInstance(param1,param2,......);
Field : 通过字节码对象获取对象的属性;
setAccessible(true); //去除私有字段的私有权限
set(Object o,"value");//修改该对象的该属性的值
Class clazz = Class.forName("com.heima.bean.Person");
Constructor c = clazz.getConstructor(String.class,int.class); //1- 获取有参构造
Person p = (Person) c.newInstance("张三",23); //2- 通过有参构造创建对象
//因为name属性为私有的,用下面注释掉的代码无法获取
//Field f = clazz.getField("name"); //3- 获取姓名字段
//f.set(p, "李四"); //4- 修改姓名的值
Field f = clazz.getDeclaredField("name"); //5- 暴力反射获取字段
f.setAccessible(true); //6- 去除私有权限
f.set(p, "李四"); //7- 修改字段值
System.out.println(p);
4- 通过反射获取方法并使用
public static String getClassName() throws IOException {
String className = null;
Properties properties = new Properties();
properties.load(new FileInputStream("config.properties"));
className = properties.getProperty("className");
return className;
}
String className = getClassName();
Class clazz = Class.forName(className);
Constructor c = clazz.getConstructor(String.class, Integer.class);
Person p = (Person) c.newInstance("Tom1",26);
//1- 获取非私有无参数无返回值的方法并调用
Method eat = clazz.getMethod("eat");
eat.invoke(p);
//2- 获取私有的无参数无返回值的方法并使用
Method sleep = clazz.getDeclaredMethod("sleep");
sleep.setAccessible(true);
sleep.invoke(p);
//3- 获取有参数的方法
Method eat1 = clazz.getMethod("eat", Apple.class);
eat1.invoke(p,new Apple());
//4- 获取有返回值的方法
Method getNameAndAge = clazz.getMethod("getNameAndAge");
String nameAndAge = (String) getNameAndAge.invoke(p);
System.out.println(nameAndAge);
5- 集合里面不一定只能存储一种类型的数据。
ArrayList<Integer> list = new ArrayList<>();
list.add(111);
list.add(222);
//list.add("abc");
Class<ArrayList> clazz = ArrayList.class; //
Method add = clazz.getMethod("add", Object.class); // 获取add方法
Person p = new Person("Tom1", 27);
add.invoke(list,p);
add.invoke(list,"abc");
System.out.println(list);
[111, 222, Person{name='Tom1', age=27}, abc]