反射(第一次写博客,格式还望朋友们指点)
通过类的字节码文件,操作类的属性,方法,构造,不需要通过对象就能实现
class对象获取方式:
1.类名.class
2.实例.getClass
3.Class.forName()
操作构造器:
获得任意修饰符的构造器对象
getDeclaredConstructor(Obj.class)
创建对象
newInstance(Object)
设置暴力反射--无视权限
setAccessible(true)
操作方法:
获得任意修饰符的方法对象
getDeclaredMethod(Obj.class...)
执行方法
invoke(实例, 实参)
操作变量:
获得任意修饰符的属性对象
getDeclaredField(属性名)
设置属性
set(实例,属性值)
练习实例:
@Test
public void test03() throws Exception{
//获取字节码文件
Class<Student> c = Student.class;
//暴力反射创建对象
Constructor<Student> con = c.getDeclaredConstructor();
con.setAccessible(true);
Student stu = con.newInstance();
Class<? extends Student> c2 = stu.getClass();
//暴力反射操作方法
Method method = c.getDeclaredMethod("eat", String.class);
method.setAccessible(true);
method.invoke(stu,"apple");
//操作属性
Field name = c2.getDeclaredField("name");
name.setAccessible(true);
name.set(stu,"张三");
System.out.println(stu);
}
动态代理
不修改方法源码的情况下,增强被代理对象方法的功能
API介绍:
获取动态代理对象
Proxy.newProxyInstance()
获取类加载器
bean.class.getClassLoader()
获取接口数组
bean.class.getInterfaces()
练习实例:
//代理集合add方法,输入指定格式字符串,向集合添加Student对象
@Test
public void dong02() throws Exception{
ArrayList<Integer> list = new ArrayList<>();
//创建动态代理对象
List proxyList=(List<Student>) Proxy.newProxyInstance(
list.getClass().getClassLoader(),
list.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//判断是否是add方法
if ("add".equals(method.getName())){
//操作实参,封装成对象
String str=(String)args[0];
String[] sp = str.split(",");
Integer zero= Integer.valueOf(sp[0]);
String one=sp[1];
String two=sp[2];
Student stu=new Student(zero,one,two);
//完成方法代理,向集合添加对象
return method.invoke(list,new Object[]{stu});
}else {
return method.invoke(list,args);
}
}
}
);
//测试效果
proxyList.add("18,张三,男");
proxyList.add("18,李四,女");
for (int i = 0; i < proxyList.size(); i++) {
System.out.println(proxyList.get(i));
System.out.println(proxyList.get(i).getClass());
}
}
}