反射原理:把字节码对象通过类加载器(类加载器)获取到相应的对象(成员变量,成员方法,局部变量)
类加载器原理:
获取到当前类 Phone的对象one 的字节码对象呢?
class cal = one.getclass();
获取到Phone类字节码对象
class cal = Phone.class;
获取到
当前类的全名字符串
class cal = class.forName("全类名")
package demo; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class demo1 { public static void main(String[] args) throws IOException { //获取到类加载器对象 方式一: ClassLoader loader = ClassLoader.getSystemClassLoader(); 方式二: InputStream is = ClassLoader.getSystemResourceAsStream("config.properties"); //可加载来自于src下面的文件信息,获取到流对象 //转化成为字节输出流 InputStream is = loader.getResourceAsStream("config.properties"); //采用properpties加载数据 Properties properties = new Properties(); properties.load(is); is.close(); //获取到数据 String name = properties.getProperty("name"); String pass = properties.getProperty("pass"); System.out.println("name = " + name); System.out.println("pass = " + pass); } }
反射获取构造方法:
1. Constructor[] array1 = clazz.getConstructors(); //获取所有 public 修饰的构造方法
2. Constructor c2 = clazz.getConstructor(String.class, int.class); //获取指定的某个public修饰的构造方法。
3. Constructor[] array3 = clazz.getDeclaredConstructors(); //获取所有的构造方法,包括私有
4. Constructor c4 = clazz.getDeclaredConstructor(int.class); //获取指定的某个构造方法,包括私有
使用构造方法:
1. Object o = c.newInstance("家海"); //采用构造方法 c 去创建对象 o 根据需求传递参数
2. c.setAccessible(true); //暴力访问,取消私有 private 权限检查。
3. Object o = clazz.newInstance(); //采用字节码去创建对象,跳过了获取构造方法的过程。调用的是 系统默认无参数构造方法
获取成员变量
1. Field[] array1 = clazz.getFields(); //获取所有 public 修饰的成员变量
2. Field f2 = clazz.getField(String); //获取指定的某个public修饰的成员变量
3. Field[] array3 = clazz.getDeclaredFields(); //获取所有的成员变量,包括私有
4. Field f4 = clazz.getDeclaredField(String); //获取指定的某个成员变量,包括私有
使用成员变量
1. 设置值 genderField.set(stu,"男"); //参数1:对象 参数2:值
2. 获取值 Object value1 = genderField.get(stu); //参数: 对象, 返回值: 获取到成员变量里面的值
3. 暴力访问 genderField.setAccessible(true); //暴力访问,取消私有权限检查
获取成员方法
1. Method[] array1 = clazz.getMethods(); //获取所有 public 修饰的成员方法, 包括父类public方法
2. Method m2 = clazz.getMethod(String,Class...); //获取指定的某个public修饰的成员方法,可变参数是:方法参数的字节码
3. Method[] array3 = clazz.getDeclaredMethods(); //获取所有的成员方法,包括私有,只有自己的方法,没有父类方法
4. Method m4 = clazz.getDeclaredMethod(String, int.class, int.class); //获取指定的某个成员方法,包括私有
使用成员方法:
1. 调用方法 Object 返回值 = 方法对象.invoke(方法所在类的对象, 方法参数1, 方法参数2);
2. 暴力访问 方法对象.setAccessible(true);
username=zhangsan
password=123456
className=blb.chc03.User
package blb.chc03;
//定义用户类
public class User {
private String username;
private String password;
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
public class Test {
//读取文件的数据,给成员变量自动赋值,展示结果
public static void main(String[] args) throws Exception{
//获取到来自于文件当中的数据。
//config.properties 文件存在于 src 目录下面的
InputStream is = ClassLoader.getSystemResourceAsStream("config.properties");
Properties pp = new Properties();
pp.load(is);
String username = pp.getProperty("username");
String password = pp.getProperty("password");
String className = pp.getProperty("className");
is.close();
//采用反射的方式,获取到对象, 创建对象
Class clazz = Class.forName(className);
Constructor c = clazz.getDeclaredConstructor();
Object o = c.newInstance();
//给成员变量赋值
Field usernameFiled = clazz.getDeclaredField("username");
usernameFiled.setAccessible(true);
usernameFiled.set(o,username);
Field passwordField = clazz.getDeclaredField("password");
passwordField.setAccessible(true);
passwordField.set(o,password);
//展示结果
System.out.println("o = " + o); //o = User{username='zhangsan', password='123456'}
}
}