反射允许对封装类的字段,方法和构造函数的信息进行编程访问
获取Class对象
Class.forName(“全类名”)===源代码阶段
类名.class === 加载阶段
对象.getClass ===运行阶段
Class c1 = Class.forName("Test.Student");
Class c2 = Student.class;
Student s = new Student();
Class c3 = s.getClass();
获取构造方法
![](https://i-blog.csdnimg.cn/blog_migrate/4f5d685be3279d30b2762c29854696e0.png)
暴力反射
临时取消权限的校验,可以创建私有方法的对象
con.setAccessible(true);
Student stu = (Student) con.newInstance("张三", 23);
获取成员变量
![](https://i-blog.csdnimg.cn/blog_migrate/5e765a9b6581b65cadded1c614d54227.png)
//获取单个成员变量
Field name = c.getDeclareField("name");
//获取权限修饰符
int m = name.getModifiers();
//获取成员变量名字
String n = name.getName();
//获取成员变量数据类型
Class type = name.getType();
//获取成员变量记录的值
Student s = new Student("zhangsan", 23);
name.setAccessible(true);
String vlaue = (String) name.get(s);
//修改对象里面记录的值
name.set(s, "lisi");
获取成员方法
![](https://i-blog.csdnimg.cn/blog_migrate/c9c2e9289dc223d3fefa1dd09e92427c.png)
作用
获取一个类里面的所有信息。获取之后再执行其他的业务逻辑
结合配置文件,动态的创建对象并调用方法
把对象里面所有的成员变量名和值保存到本地文件中
public static void saveObject(Object o) throws IOException, IllegalAccessException {
Class c = o.getClass();
//创建IO流
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
//获取所有的成员变量
Field[] field = c.getDeclaredFields();
for (Field f : field) {
f.setAccessible(true);
//获取成员变量的名字
String name = f.getName();
//获取成员变量的值
Object value = f.get(o);
//写出数据
bw.write(name + "=" + value);
bw.newLine();
}
bw.close();
}
反射与动态文件相结合,动态创建对象并调用方法
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1.读取配置文件中的信息
Properties p = new Properties();
FileInputStream fis = new FileInputStream("a.txt");
p.load(fis);
fis.close();
//2.获取全类名和方法名
String className = (String) p.get("classname");
String methodName = (String) p.get("method");
//3.利用反射创建对象并运行方法
Class c = Class.forName(className);
//获取构造方法
Constructor con = c.getDeclaredConstructor();
Object o = con.newInstance();
//获取成员方法并运行
Method m = c.getDeclaredMethod(methodName);
m.setAccessible(true);
m.invoke(o);
}
动态代理
无侵入式的给代码增加额外的功能
代理里面就是要对象被代理的方法
通过接口保证,后面的对象和代理需要实现同一个接口,接口中就是被代理的所有方法
Star star = (Star) Proxy.newProxyInstance(
ProxyUtil.class.getClassLoader(),//指定用哪个类的加载器,去加载生成的代理类
new Class[]{Star.class},//指定接口,这些接口用于指定生成的代理长什么样,有哪些方法
new InvocationHandler() {//用来指定生成的对象要干什么事情
public Object invoke(Object proxy, Method method, Object[] args) throw Throwable {
if ("sing".equals(method.getName())){
System.out.println("开始唱歌");}
return method.invoke(star, args);
}
};
return star;
}
}