----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
1 分析JVM动态生成的类
创建实现了Collection接口的动态类和查看其名称,分析Proxy.getProxyClass方法的各个参数。
编码列出动态类中的所有构造方法和参数签名
编码列出动态类中的所有方法和参数签名
创建动态类的实例对象
用反射获得构造方法
编写一个最简单的InvocationHandler类
调用构造方法创建动态类的实例对象,并将编写的InvocationHandler类的实例对象传进去
打印创建的对象和调用对象的没有返回值的方法和getClass方法,演示调用其他有返回值的方法报告了异常。
将创建动态类的实例对象的代理改成匿名内部类的形式编写,锻炼大家习惯匿名内部类。
用下面的代码可以吗?
clazz.newInstance() ;
clazz.getConstructor().newInstance();
答:不可以,newInstance()用的是实例参数
2 代码分析:
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ClassLoader loader = Collection.class.getClassLoader(); //类加载器
Class clazzProxy = Proxy.getProxyClass(loader, Collection.class);
System.out.println(clazzProxy.getName());//类名
Constructor constructor = clazzProxy.getConstructor(InvocationHandler.class);//这个InvocationHandler是形参
Collection coll = ( Collection )constructor.newInstance( new InvocationHandler(){ //这个 InvocationHandler是实参,必须实现接口
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;
}
});//返回Collection的实例变量
System.out.println(coll);//结果为null,但这是假象,实例已经建立
coll.add(3);//出现异常,因为$Proxy类只有调用这个ClassLoader的功能,没有修删改的功能
}
3 一步到位
JVM动态生成的类
*/
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
/*一步到位
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces, //如果此对象表示一个类,则返回值是一个数组,它包含了表示该类所实现的所有接口的对象
InvocationHandler h)*/
//调用newProxyInstance方法
Collection CollectionProxy =(Collection) Proxy.newProxyInstance(
Collection.class.getClassLoader(), //类的加载器
new Class []{ Collection.class},//类中所有对象的字节码
new InvocationHandler(){ //实现的接口,接口包含Collection的方法
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
ArrayList list = new ArrayList();//定义一个集合
/*Object obj = method.invoke(proxy, args);//调用方法
list.add(obj);*/: 如果这样,则会递归调用,出现死循环
list.add(2);
System.out.println(1);
return list.toString();
}
}
);
4 分析:JVM动态生成的类
动态生成的类实现了Collection接口(可以实现若干接口),生成的类有Collection接口中的所有方法和一个如下接受InvocationHandler参数的构造方法。
构造方法接受一个InvocationHandler对象,接受对象了要干什么用呢?该方法内部的代码会是怎样的呢?
答:接受了InvocationHandler这个对象,则复写了invoke的方法,实现原来类的作用,它的内部的代码就是原来的类的代码构成。
分析为什么动态类的实例对象的getClass()方法返回了正确结果呢?
答:getClass()方法调用的是字节码,有实例对象就有字节码
调用调用代理对象的从Object类继承的hashCode, equals, 或toString这几个方法时,代理对象将调用请求转发给InvocationHandler对象,对于其他方法,则不转发调用请求
5 oop思想:封装,实现小小的框架
代码一步一步的改进的,由点到面,体现了代码的阅读性,广泛性
代码:
JVM动态生成的类
*/
public static void main(String[] args)throws Exception {
final Object list = new Object();//定义一个集合
Object obj = getProxy(list);
for(int i=0;i<10;i++)
{
System.out.println(obj.equals("2"));
}
}
public static Object getProxy(final Object ob) {
Object proxy = Proxy.newProxyInstance(
ob.getClass().getClassLoader(), //类的加载器
ob.getClass().getInterfaces(),//类中所有对象的字节码
new InvocationHandler(){ //实现的接口,接口包含Collection的方法
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
new Myadvice().sartTime();
Object obj= (Object)method.invoke(ob, args);
new Myadvice().endTime();
long allTime = new Myadvice().endTime()-new Myadvice().sartTime();
System.out.println( method.getName()+": run times : "+allTime);
return obj;
}
}
);
return proxy;
}
}
接口:package cn.itcast.day20120726;
public interface advice {
public long sartTime();
public long endTime();
}
实现接口的类
package cn.itcast.day20120726;
public class Myadvice implements advice {
public long sartTime()
{
long sartTime = System.currentTimeMillis();
System.out.println("我轻轻的来");
return sartTime;
}
public long endTime()
{
long endTime = System.currentTimeMillis();
System.out.println("我轻轻的走");
return endTime;
}
}
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------